/*! DRAGONS: We use the current UTF16String GetString 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!) */ std::list<std::string> SplitStringArray(const MDObjectPtr &Array) { std::list<std::string> Ret; // Quit early if an invalid parameter if(!Array) return Ret; // 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 SplitStringArray() - need this type to be defined in the dictionary file\n"); return Ret; } // Assemble the data value (which may be an array of sub-values) DataChunkPtr Data = Array->PutData(); // Get a pointer to the start of the data UInt8 *pData = Data->Data; // The number of bytes of data to split size_t BytesLeft = Data->Size; while(BytesLeft > 1) { // Find the end of the current string size_t Len = 0; UInt8 *p = pData; while(BytesLeft > 1) { BytesLeft -= 2; Len += 2; UInt16 Char = GetU16(p); p += 2; // End when we find a null if(Char == 0) break; } // Copy this string to the working value Value->SetValue(pData, Len); // Read out the traits-formatted version of the string Ret.push_back(Value->GetString()); // Move the pointer forward to the next value after the string terminator pData = 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); }