/* * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2008 Apple Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The 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( QTSS_AttrDataType inType) { if (inType < qtssAttrDataTypeNumTypes) return kDataTypeStrings[inType]; return kDataTypeStrings[qtssAttrDataTypeUnknown]; } QTSS_AttrDataType QTSSDataConverter::TypeStringToType( char* inTypeString) { for (UInt32 x = 0; x < qtssAttrDataTypeNumTypes; x++) { StrPtrLen theTypeStrPtr(inTypeString); if (theTypeStrPtr.EqualIgnoreCase(kDataTypeStrings[x], ::strlen(kDataTypeStrings[x]))) return x; } return qtssAttrDataTypeUnknown; } QTSS_Error QTSSDataConverter::StringToValue( char* inValueAsString, 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(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 = "%d"; } break; case qtssAttrDataTypeUInt32: { theBufSize = sizeof(UInt32); theFormat = "%u"; } 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( 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[(UInt8) (*inValueAsString++) ] * 16; if (*inValueAsString != 0) char2 = sCharToNums[(UInt8) (*inValueAsString++)]; else char2 = 0; *dataPtr++ = char1 + char2; } *ioBufSize = dataLen; return QTSS_NoErr; } char* QTSSDataConverter::ConvertBytesToCHexString( 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( 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) { Bool16* theBoolPtr = (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: qtss_sprintf(theString, "%hu", *( UInt16*)inValue); break; case qtssAttrDataTypeSInt16: qtss_sprintf(theString, "%hd", *( SInt16*)inValue); break; case qtssAttrDataTypeSInt32: qtss_sprintf(theString, "%"_S32BITARG_, *( SInt32*)inValue); break; case qtssAttrDataTypeUInt32: qtss_sprintf(theString, "%"_U32BITARG_, *( UInt32*)inValue); break; case qtssAttrDataTypeSInt64: qtss_sprintf(theString, "%"_64BITARG_"d", *( SInt64*)inValue); break; case qtssAttrDataTypeUInt64: qtss_sprintf(theString, "%"_64BITARG_"u", *( UInt64*)inValue); break; case qtssAttrDataTypeFloat32: qtss_sprintf(theString, "%f", *( Float32*)inValue); break; case qtssAttrDataTypeFloat64: qtss_sprintf(theString, "%f", *( Float64*)inValue); break; case qtssAttrDataTypeTimeVal: qtss_sprintf(theString, "%"_64BITARG_"d", *( SInt64*)inValue); break; default: delete theString; theString = ConvertBytesToCHexString(inValue, inValueLen); } return theString; }