//! Set a data chunk from a hex string DataChunkPtr mxflib::Hex2DataChunk(std::string Hex) { // Build the result chunk DataChunkPtr Ret = new DataChunk(); // Use a granularity of 16 as most hex strings are likely to be 16 or 32 bytes // DRAGONS: We may want to revise this later Ret->SetGranularity(16); // Index the hex string char const *p = Hex.c_str(); int Size = 0; int Value = -1; // During this loop Value = -1 when no digits of a number are mid-process // This stops a double space being regarded as a small zero in between two spaces // It also stops a trailing zero being appended to the data if the last character // before the terminating byte is not a hex digit. do { int digit; if(*p >= '0' && *p <='9') digit = (*p) - '0'; else if(*p >= 'a' && *p <= 'f') digit = (*p) - 'a' + 10; else if(*p >= 'A' && *p <= 'F') digit = (*p) - 'A' + 10; else if(Value == -1) { // Skip second or subsiquent non-digit continue; } else { Size++; Ret->Resize(Size); Ret->Data[Size-1] = Value; Value = -1; continue; } if(Value == -1) Value = 0; else Value <<=4; Value += digit; // Note that the loop test is done in this way to force // a final cycle of the loop with *p == 0 to allow the last // number to be processed } while(*(p++)); return Ret; }
/*! DRAGONS: We use the current UTF16String SetString trait to ensure that we always have the correct handling, * even if the user wants these strings handled differently (i.e. we do it their way!) */ void SetStringArray(MDObjectPtr &Array, const std::list<std::string> &Strings) { // Abort if we are send a NULL pointer if(!Array) return; // Don't bother if we have nothing to do if(Strings.empty()) return; // Build a working string static MDTypePtr ValType = MDType::Find("UTF16String"); MDObjectPtr Value = ValType ? new MDObject(ValType) : NULL; if(!Value) { error("Can't build UTF16String value required by SetStringArray() - need this type to be defined in the dictionary file\n"); return; } // Get a buffer in which to build the final string array, make it quite granular as it will keep growing DataChunkPtr Buffer = new DataChunk(); Buffer->SetGranularity(16 * 1024); std::list<std::string>::const_iterator it = Strings.begin(); while(it != Strings.end()) { Value->SetString(*it); DataChunkPtr ThisString = Value->PutData(); Buffer->Append(ThisString); // Add terminator if required, i.e. if the sub-string we just added did not end in a zero UInt8 *p = &ThisString->Data[ThisString->Size]; // Terminate if either of the last two bytes in the current buffer is non-zero - or if the string was too short to have a terminator if((ThisString->Size) < 2 || ((*(--p) != 0) || (*(--p) != 0))) { const UInt8 Term[2] = { 0, 0}; Buffer->Set(2, Term, Buffer->Size); } it++; } // Set the value from this buffer Array->SetValue(Buffer); }