/* * P4TypeConversions.mm * SCMMenuExtra * * Created by Michael Bishop on 1/29/10. * Copyright 2010 Perforce Software. All rights reserved. * */ #include "P4TypeConversions.hpp" #include "clientapi.h" #import "P4ClientApi.h" static NSString * StringFromUtf8Bytes( const char * bytes, size_t length ); static NSString * StringFromUtf8StrPtr( const StrPtr * str ); static NSString * StringFromUtf8StrPtr( const StrPtr & str ); static NSString * StringFromUtf8CString( const char * str ); static NSDictionary * DictionaryFromStrDict( const StrDict * strDict ); /*===================================================================\ | | | Utility Conversion Methods | | | \===================================================================*/ @implementation NSString (P4TypeConversions) -(StrRef)strRef; { return StrRef( [self UTF8String] ); } -(StrBuf)strBuf; { return StrBuf( [self UTF8String] ); } +(NSString*)stringWithStrPtr:(const StrPtr&)strptr { return StringFromUtf8StrPtr(strptr); } @end @implementation NSDictionary (P4TypeConversions) +(NSDictionary*)dictionaryWithStrDict:(const StrDict&)strDict { return DictionaryFromStrDict(&strDict); } @end NSString * StringFromUtf8Bytes( const char * bytes, size_t length ) { if ( !bytes ) return nil; NSString * s = [[[NSString alloc] initWithBytes:const_cast((const void *)bytes) length:length encoding:NSUTF8StringEncoding] autorelease]; // I'd really like to be able to do this without creating copies but // it'd be up to the receiving end to make a copy if it needed to. It // would also have to be documented well return s; } NSString * StringFromUtf8StrPtr( const StrPtr * str ) { if ( !str ) return nil; return StringFromUtf8StrPtr( *str ); } NSString * StringFromUtf8StrPtr( const StrPtr & str ) { if ( !str.Text() ) return nil; return StringFromUtf8Bytes( str.Text(), str.Length() ); } NSString * StringFromUtf8CString( const char * str ) { if ( !str ) return nil; return StringFromUtf8Bytes( str, strlen(str) ); } NSDictionary * DictionaryFromStrDict( const StrDict * strDict ) { if ( !strDict ) return nil; // Convert the StrDict to an NSDictionary // NSMutableDictionary * dict = [[[NSMutableDictionary alloc] init] autorelease]; StrRef var, val; int i = 0; while ( const_cast(strDict)->GetVar( i, var, val ) ) { NSString * v = StringFromUtf8StrPtr( &val ); NSString * k = StringFromUtf8StrPtr( &var ); [dict setValue:v forKey:k]; i++; } return [NSDictionary dictionaryWithDictionary:dict]; // passes an immutable dictionary } @implementation NSError (P4TypeConversions) +(id)errorWithP4Error:(const Error&)error { return [[[NSError alloc] initWithP4Error:&error] autorelease]; } -(id)init { return [self initWithP4Error:NULL]; } -(id)initWithP4Error:(const Error*)error { if (!error) { [self autorelease]; return nil; } StrBuf message; error->Fmt(message, EF_PLAIN); NSString * localizedMessage = StringFromUtf8StrPtr( &message ); ErrorId * errorId = error->GetId(0); int code = errorId->code; NSValue * subSystem = [NSNumber numberWithInt:errorId->Subsystem()]; NSValue * subCode = [NSNumber numberWithInt:errorId->SubCode()]; NSValue * severity = [NSNumber numberWithInt:errorId->Severity()]; NSValue * generic = [NSNumber numberWithInt:errorId->Generic()]; NSDictionary * userInfo = [NSDictionary dictionaryWithObjectsAndKeys: localizedMessage, NSLocalizedDescriptionKey, subSystem, P4SubsystemErrorKey, subCode, P4SubCodeErrorKey, severity, P4SeverityErrorKey, generic, P4GenericErrorKey, nil]; // TODO: It'd be nice to do something with the underlying errors as they are retained only in the Fmt method. // There is a key for them NSUnderlyingErrorKey if (!(self = [self initWithDomain:P4ErrorDomain code:code userInfo:userInfo]) ) return nil; return self; } @end