// // P4Map.m // P4Menu // // Created by Michael Bishop on 12/13/11. // Copyright (c) 2011 Numerical Garden LLC. All rights reserved. // #include "stdhdrs.h" #include "strbuf.h" #include "mapapi.h" #import "P4Mapper.h" #import "P4TypeConversions.hpp" static MapApi * NewMapApiWithEntries(NSArray* entries); static MapDir MapDirFromDirection( const P4MappingDirection direction ); static P4MapEntryType P4MapEntryTypeFromMapType( const MapType type ); static NSArray * EntriesFromMapApi( MapApi & mapApi ); #pragma mark - @interface P4MapEntry () +(P4MapEntry*)entryWithMapApi:(MapApi &)mapApi atIndex:(int)index; -(MapType)p4MapType; -(NSString*)typeString; -(NSString*)stringValue; @end #pragma mark - @implementation P4Mapper @synthesize entries = _entries; -(id)initWithMapApi:( MapApi & )mapApi { if ( !(self = [super init]) ) return nil; self.entries = EntriesFromMapApi( mapApi ); return self; } -(void)dealloc { delete (MapApi*)_api; [super dealloc]; } -(NSString*)description { NSMutableArray * entryStrings = [NSMutableArray arrayWithCapacity:self.entries.count]; for (P4MapEntry * entry in self.entries) [entryStrings addObject:[entry stringValue]]; return [entryStrings componentsJoinedByString:@"\n"]; } -(void)setEntries:(NSArray *)entries { if ( _entries == entries ) return; [_entries release]; _entries = [entries copy]; delete (MapApi*)_api; _api = NULL; } -(MapApi*)api { if ( !_api ) _api = NewMapApiWithEntries( self.entries ); return (MapApi*)_api; } -(NSString*)pathByMappingPath:(NSString*)path direction:(P4MappingDirection)direction { StrBuf translatedPathBuf; if (self.api->Translate( [path strRef], translatedPathBuf, MapDirFromDirection(direction) )) return [NSString stringWithStrPtr:translatedPathBuf]; return nil; } -(P4Mapper*)mapperByJoiningWithMapper:(P4Mapper*)rightMapper { MapApi * joinedMapApi = MapApi::Join(self.api, rightMapper.api); P4Mapper * mapper = [[[P4Mapper alloc] initWithMapApi:*joinedMapApi] autorelease]; delete joinedMapApi; return mapper; } -(P4Mapper*)mapperByJoiningInDirection:(P4MappingDirection)direction withMapper:(P4Mapper*)rightMapper inDirection:(P4MappingDirection)rightDirection { MapApi * joinedMapApi = MapApi::Join(self.api, MapDirFromDirection(direction), rightMapper.api, MapDirFromDirection(rightDirection)); P4Mapper * mapper = [[[P4Mapper alloc] initWithMapApi:*joinedMapApi] autorelease]; delete joinedMapApi; return mapper; } @end #pragma mark - @implementation P4MapEntry @synthesize type = _type; @synthesize leftPath = _leftPath; @synthesize rightPath = _rightPath; +(P4MapEntry*)entryWithMapApi:(MapApi &)mapApi atIndex:(int)index { if ( index >= mapApi.Count() ) return nil; P4MapEntry * entry = [[[P4MapEntry alloc] init] autorelease]; entry.type = P4MapEntryTypeFromMapType(mapApi.GetType(index)); if ( (mapApi.GetLeft(index)) ) entry.leftPath = [NSString stringWithStrPtr:*(mapApi.GetLeft(index))]; if ( (mapApi.GetRight(index)) ) entry.rightPath = [NSString stringWithStrPtr:*(mapApi.GetRight(index))]; return entry; } +(P4MapEntry*)entryWithEntryString:(NSString*)entryString { // TODO: Test with a space in the path // TODO: Test with a '//' in the path if ( !entryString ) return nil; if ( !entryString.length ) return nil; P4MapEntry * entry = [[P4MapEntry new] autorelease]; NSScanner * scanner = [NSScanner scannerWithString:entryString]; NSString * typeString = nil; NSString * leftPath = nil; NSString * rightPath = nil; // TYPE [scanner scanUpToString:@"//" intoString:&typeString]; [scanner setScanLocation:[scanner scanLocation] + 1]; // LEFT [scanner scanUpToString:@"//" intoString:&leftPath]; leftPath = [@"/" stringByAppendingString:leftPath]; // RIGHT rightPath = [[scanner string] substringFromIndex:[scanner scanLocation]]; if ([typeString hasPrefix:@"+"]) entry.type = P4MapEntryTypeOverlay; if ([typeString hasPrefix:@"-"]) entry.type = P4MapEntryTypeExclude; entry.leftPath = leftPath; entry.rightPath = rightPath; return entry; } +(P4MapEntry*)entryWithLeftPath:(NSString*)leftPath { return [P4MapEntry entryWithLeftPath:leftPath type:P4MapEntryTypeInclude]; } +(P4MapEntry*)entryWithLeftPath:(NSString*)leftPath type:(P4MapEntryType)type { return [P4MapEntry entryWithLeftPath:leftPath rightPath:nil type:type]; } +(P4MapEntry*)entryWithLeftPath:(NSString*)leftPath rightPath:(NSString*)rightPath { return [P4MapEntry entryWithLeftPath:leftPath rightPath:rightPath type:P4MapEntryTypeInclude]; } +(P4MapEntry*)entryWithLeftPath:(NSString*)leftPath rightPath:(NSString*)rightPath type:(P4MapEntryType)type { P4MapEntry * entry = [[[P4MapEntry alloc] init] autorelease]; entry.leftPath = leftPath; entry.rightPath = rightPath; entry.type = type; return entry; } -(NSString*)description { return [self stringValue]; } -(NSString*)stringValue { NSMutableString * stringValue = [NSMutableString string]; if ( self.typeString ) [stringValue appendFormat:@"%@ ", self.typeString]; [stringValue appendString:self.leftPath]; if ( self.rightPath ) [stringValue appendFormat:@" %@", self.rightPath]; return stringValue; } -(NSString*)typeString { switch (self.type) { case P4MapEntryTypeExclude: return @"-"; case P4MapEntryTypeOverlay: return @"+"; default: return nil; } } -(MapType)p4MapType { switch (self.type) { case P4MapEntryTypeExclude: return MapExclude; case P4MapEntryTypeOverlay: return MapOverlay; default: return MapInclude; } } @end #pragma mark - MapApi * NewMapApiWithEntries(NSArray* entries) { MapApi * mapApi = new MapApi(); for (P4MapEntry * entry in entries) { mapApi->Insert([entry.leftPath strRef], [entry.rightPath strRef],entry.p4MapType ); } return mapApi; } MapDir MapDirFromDirection( const P4MappingDirection direction ) { switch (direction) { case P4MappingDirectionRightToLeft: return MapRightLeft; default: return MapLeftRight; } } P4MapEntryType P4MapEntryTypeFromMapType( const MapType type ) { switch (type) { case MapExclude: return P4MapEntryTypeExclude; case MapOverlay: return P4MapEntryTypeOverlay; default: return P4MapEntryTypeInclude; } } NSArray * EntriesFromMapApi( MapApi & mapApi ) { NSMutableArray * array = [NSMutableArray arrayWithCapacity:mapApi.Count()]; for (int i = 0; i