/* * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2001 Apple Computer, Inc. All Rights Reserved. The * contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please * obtain a copy of the License at http://www.apple.com/publicsource and * read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please * see the License for the specific language governing rights and * limitations under the License. * * * @APPLE_LICENSE_HEADER_END@ * */ /* File: QTSSDataConverter.cpp Contains: Utility routines for converting to and from QTSS_AttrDataTypes and text Written By: Denis Serenyi Change History (most recent first): */ #include "QTSSDataConverter.h" #include "StrPtrLen.h" #include "OSMemory.h" #include #include static const StrPtrLen kEnabledStr("true"); static const StrPtrLen kDisabledStr("false"); static char* kDataTypeStrings[] = { "Unknown", "CharArray", "Bool16", "SInt16", "UInt16", "SInt32", "UInt32", "SInt64", "UInt64", "QTSS_Object", "QTSS_StreamRef", "Float32", "Float64", "VoidPointer", "QTSS_TimeVal" }; static const char* kHEXChars={ "0123456789ABCDEF" }; static const UInt8 sCharToNums[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0-9 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10-19 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20-29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //30-39 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, //40-49 - 48 = '0' 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, //50-59 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, //60-69 A-F 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, //70-79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //80-89 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, //90-99 a-f 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, //100-109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //110-119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //120-129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //130-139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140-149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150-159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160-169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170-179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180-189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190-199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200-209 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210-219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220-229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230-239 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240-249 0, 0, 0, 0, 0, 0 //250-255 }; char* QTSSDataConverter::TypeToTypeString(const QTSS_AttrDataType inType) { if (inType < qtssAttrDataTypeNumTypes) return kDataTypeStrings[inType]; return kDataTypeStrings[qtssAttrDataTypeUnknown]; } QTSS_AttrDataType QTSSDataConverter::TypeStringToType(const char* inTypeString) { for (UInt32 x = 0; x < qtssAttrDataTypeNumTypes; x++) { StrPtrLen theTypeStrPtr((char*)inTypeString); if (theTypeStrPtr.EqualIgnoreCase(kDataTypeStrings[x], ::strlen(kDataTypeStrings[x]))) return x; } return qtssAttrDataTypeUnknown; } QTSS_Error QTSSDataConverter::StringToValue( const char* inValueAsString, const QTSS_AttrDataType inType, void* ioBuffer, UInt32* ioBufSize) { UInt32 theBufSize = 0; char* theFormat = NULL; if ( inValueAsString == NULL || ioBufSize == NULL) return QTSS_BadArgument; if ( inType == qtssAttrDataTypeCharArray ) { // // If this data type is a string, copy the string into // the destination buffer UInt32 theLen = ::strlen(inValueAsString); // // First check to see if the destination is big enough if ((ioBuffer == NULL) || (*ioBufSize < theLen)) { *ioBufSize = theLen; return QTSS_NotEnoughSpace; } // // Do the string copy. Use memcpy for speed. ::memcpy(ioBuffer, inValueAsString, theLen); *ioBufSize = theLen; return QTSS_NoErr; } if (inType == qtssAttrDataTypeBool16) { // // The text "enabled" means true, anything else means false if (*ioBufSize < sizeof(Bool16)) { *ioBufSize = sizeof(Bool16); return QTSS_NotEnoughSpace; } Bool16* it = (Bool16*)ioBuffer; StrPtrLen theValuePtr((char*)inValueAsString); if (kEnabledStr.EqualIgnoreCase(inValueAsString, ::strlen(inValueAsString))) *it = true; else *it = false; *ioBufSize = sizeof(Bool16); return QTSS_NoErr; } // // If this is another type, format the string into that type switch ( inType ) { case qtssAttrDataTypeUInt16: { theBufSize = sizeof(UInt16); theFormat = "%hu"; } break; case qtssAttrDataTypeSInt16: { theBufSize = sizeof(SInt16); theFormat = "%hd"; } break; case qtssAttrDataTypeSInt32: { theBufSize = sizeof(SInt32); theFormat = "%ld"; } break; case qtssAttrDataTypeUInt32: { theBufSize = sizeof(UInt32); theFormat = "%lu"; } break; case qtssAttrDataTypeSInt64: { theBufSize = sizeof(SInt64); theFormat = "%"_64BITARG_"d"; } break; case qtssAttrDataTypeUInt64: { theBufSize = sizeof(UInt64); theFormat = "%"_64BITARG_"u"; } break; case qtssAttrDataTypeFloat32: { theBufSize = sizeof(Float32); theFormat = "%f"; } break; case qtssAttrDataTypeFloat64: { theBufSize = sizeof(Float64); theFormat = "%f"; } break; case qtssAttrDataTypeTimeVal: { theBufSize = sizeof(SInt64); theFormat = "%"_64BITARG_"d"; } break; default: return ConvertCHexStringToBytes(inValueAsString,ioBuffer,ioBufSize); } if (( ioBuffer == NULL) || (*ioBufSize < theBufSize )) { *ioBufSize = theBufSize; return QTSS_NotEnoughSpace; } *ioBufSize = theBufSize; ::sscanf(inValueAsString, theFormat, ioBuffer); return QTSS_NoErr; } QTSS_Error QTSSDataConverter::ConvertCHexStringToBytes( const char* inValueAsString, void* ioBuffer, UInt32* ioBufSize) { UInt32 stringLen = ::strlen(inValueAsString) ; UInt32 dataLen = (stringLen + (stringLen & 1 ? 1 : 0)) / 2; // First check to see if the destination is big enough if ((ioBuffer == NULL) || (*ioBufSize < dataLen)) { *ioBufSize = dataLen; return QTSS_NotEnoughSpace; } UInt8* dataPtr = (UInt8*) ioBuffer; UInt8 char1, char2; while (*inValueAsString) { char1 = sCharToNums[*inValueAsString++] * 16; if (*inValueAsString != 0) char2 = sCharToNums[*inValueAsString++]; else char2 = 0; *dataPtr++ = char1 + char2; } *ioBufSize = dataLen; return QTSS_NoErr; } char* QTSSDataConverter::ConvertBytesToCHexString(const void* inValue, const UInt32 inValueLen) { UInt8* theDataPtr = (UInt8*) inValue; UInt32 len = inValueLen *2; char *theString = NEW char[len+1]; char *resultStr = theString; if (theString != NULL) { UInt8 temp; UInt32 count = 0; for (count = 0; count < inValueLen; count++) { temp = *theDataPtr++; *theString++ = kHEXChars[temp >> 4]; *theString++ = kHEXChars[temp & 0xF]; } *theString = 0; } return resultStr; } char* QTSSDataConverter::ValueToString( const void* inValue, const UInt32 inValueLen, const QTSS_AttrDataType inType) { if (inValue == NULL) return NULL; if ( inType == qtssAttrDataTypeCharArray ) { StrPtrLen theStringPtr((char*)inValue, inValueLen); return theStringPtr.GetAsCString(); } if (inType == qtssAttrDataTypeBool16) { const Bool16* theBoolPtr = (const Bool16*)inValue; if (*theBoolPtr) return kEnabledStr.GetAsCString(); else return kDisabledStr.GetAsCString(); } // // With these other types, its impossible to tell how big they'll // be, so just allocate some buffer and hope we fit. char* theString = NEW char[128]; // // If this is another type, format the string into that type switch ( inType ) { case qtssAttrDataTypeUInt16: ::sprintf(theString, "%hu", *(const UInt16*)inValue); break; case qtssAttrDataTypeSInt16: ::sprintf(theString, "%hd", *(const SInt16*)inValue); break; case qtssAttrDataTypeSInt32: ::sprintf(theString, "%ld", *(const SInt32*)inValue); break; case qtssAttrDataTypeUInt32: ::sprintf(theString, "%lu", *(const UInt32*)inValue); break; case qtssAttrDataTypeSInt64: ::sprintf(theString, "%"_64BITARG_"d", *(const SInt64*)inValue); break; case qtssAttrDataTypeUInt64: ::sprintf(theString, "%"_64BITARG_"u", *(const UInt64*)inValue); break; case qtssAttrDataTypeFloat32: ::sprintf(theString, "%f", *(const Float32*)inValue); break; case qtssAttrDataTypeFloat64: ::sprintf(theString, "%f", *(const Float64*)inValue); break; case qtssAttrDataTypeTimeVal: ::sprintf(theString, "%"_64BITARG_"d", *(const SInt64*)inValue); break; default: delete theString; theString = ConvertBytesToCHexString(inValue, inValueLen); } return theString; }