#include "munga.h" #include "cstr.h" #include "memstrm.h" //namespace Munga //{ rString StringRepresentation::operator+=(char chr) { Check(this); size_t len = strlen(&firstByte); *(&firstByte + len++) = chr; *(&firstByte + len) = '\0'; return *this; } #if defined(USE_SIGNATURE) int Is_Signature_Bad(const StringRepresentation *) { return false; } #endif MemoryStream& MemoryStream_Read(MemoryStream *stream, StringRepresentation *str) { Check(stream); Check(str); pString ptr = *str; for (*stream >> ptr[(size_t)0]; ptr[(size_t)0]; ++ptr) *stream >> ptr[(size_t)0]; return *stream; } MemoryStream& MemoryStream_Write(MemoryStream *stream, const StringRepresentation &str) { Check(stream); Check(&str); return stream->WriteBytes((const char*)str, str.GetLength() + 1); } #define DELETE_FILL_CHAR ('0') size_t CStringRepresentation::allocationIncrement = 8; inline size_t CStringRepresentation::CalculateSize(size_t needed) { Verify(!Small_Enough(allocationIncrement)); size_t x = ((needed + allocationIncrement) / allocationIncrement) * allocationIncrement; return x; } CStringRepresentation::CStringRepresentation() { stringLength = 0; stringSize = 0; stringText = NULL; referenceCount = 0; } CStringRepresentation::CStringRepresentation(const CStringRepresentation &str) { Check(&str); stringLength = str.stringLength; stringSize = str.stringSize; if (str.stringText == NULL) stringText = NULL; else { stringText = new char[stringSize]; Register_Pointer(stringText); Mem_Copy(stringText, str.stringText, stringLength + 1, stringSize); } referenceCount = 0; } CStringRepresentation::CStringRepresentation(const char *cstr) { if ((cstr == NULL) || (cstr[0] == '\x00')) { stringLength = 0; stringSize = 0; stringText = NULL; } else { stringLength = strlen(cstr); stringSize = CalculateSize(stringLength); stringText = new char[stringSize]; Register_Pointer(stringText); Mem_Copy(stringText, cstr, stringLength + 1, stringSize); } referenceCount = 0; } CStringRepresentation::~CStringRepresentation() { if (stringText != NULL) { #if DEBUG_LEVEL>0 memset(stringText, DELETE_FILL_CHAR, stringSize); #endif Unregister_Pointer(stringText); delete[] stringText; } } Logical CStringRepresentation::TestInstance() const { if (stringText == NULL) { Verify(stringSize == 0); Verify(stringLength == 0); } else { Verify(stringSize > 0); Verify(stringLength == strlen(stringText)); } return true; } CStringRepresentation CStringRepresentation::operator = (const CStringRepresentation &str) { Check(this); if (this == &str) return *this; if (stringText != NULL) { #if DEBUG_LEVEL>0 memset(stringText, DELETE_FILL_CHAR, stringSize); #endif Unregister_Pointer(stringText); delete[] stringText; } Check(&str); stringLength = str.stringLength; stringSize = str.stringSize; if (stringSize == 0) stringText = NULL; else { stringText = new char[stringSize]; Register_Pointer(stringText); Mem_Copy(stringText, str.stringText, stringLength + 1, stringSize); } return *this; } CStringRepresentation CStringRepresentation::operator = (const char *cstr) { Check(this); if (stringText != NULL) { #if DEBUG_LEVEL>0 memset(stringText, DELETE_FILL_CHAR, stringSize); #endif Unregister_Pointer(stringText); delete[] stringText; } if ((cstr == NULL) || (cstr[0] == '\x00')) { stringLength = 0; stringSize = 0; stringText = NULL; } else { stringLength = strlen(cstr); stringSize = CalculateSize(stringLength); stringText = new char[stringSize]; Register_Pointer(stringText); Mem_Copy(stringText, cstr, stringLength + 1, stringSize); } return *this; } CStringRepresentation operator + (const CStringRepresentation &str1, const CStringRepresentation &str2) { Check(&str1); Check(&str2); CStringRepresentation temp; unsigned long totalLen = str1.stringLength + str2.stringLength; if (totalLen == 0) return temp; temp.stringLength = 0; temp.stringSize = CStringRepresentation::CalculateSize((size_t)totalLen); temp.stringText = new char[temp.stringSize]; Register_Pointer(temp.stringText); Verify(temp.stringSize >= 1); temp.stringText[0] = '\000'; if (str1.stringText != NULL) { Mem_Copy(temp.stringText, str1.stringText, str1.stringLength, temp.stringSize); temp.stringLength = str1.stringLength; } if (str2.stringText != NULL) { Verify(temp.stringLength < temp.stringSize); Mem_Copy(&temp.stringText[temp.stringLength], str2.stringText, str2.stringLength + 1, temp.stringSize - temp.stringLength); temp.stringLength += str2.stringLength; } Check(&temp); return temp; } CStringRepresentation operator + (const CStringRepresentation &str, char ch) { Check(&str); CStringRepresentation temp; if (str.stringText == NULL) { temp.stringLength = 1; temp.stringSize = CStringRepresentation::allocationIncrement; temp.stringText = new char [temp.stringSize]; Register_Pointer(temp.stringText); Verify(temp.stringSize >= 2); temp.stringText[0] = ch; temp.stringText[1] = '\000'; } else { Verify(str.stringLength != UINT_MAX); temp.stringLength = str.stringLength + 1; if (temp.stringLength == str.stringSize) temp.stringSize = str.stringSize + CStringRepresentation::allocationIncrement; else temp.stringSize = str.stringSize; temp.stringText = new char[temp.stringSize]; Register_Pointer(temp.stringText); Mem_Copy(temp.stringText, str.stringText, str.stringLength, temp.stringSize); Verify(str.stringLength < temp.stringSize); Verify(temp.stringLength < temp.stringSize); temp.stringText[str.stringLength] = ch; temp.stringText[temp.stringLength] = '\000'; } Check(&temp); return temp; } int CStringRepresentation::Compare(const CStringRepresentation &str) const { Check(this); Check(&str); // handle special cases where one string is empty if (stringText == NULL) { if (str.stringText == NULL) return 0; else return -1; } if (str.stringText == NULL) return 1; return strcmp(stringText, str.stringText); } CStringRepresentation CStringRepresentation::GetNthToken(size_t nth_token, char *delimiters) const { Check(this); // // Which delimters to use // char *delimter_string = " \t,"; if (delimiters != NULL) delimter_string = delimiters; Check_Pointer(delimter_string); // // Make temporary // CStringRepresentation temp(*this); if (temp.stringText == NULL) return temp; // // Parse string with strtok // size_t i; char *ptr; Check_Pointer(temp.stringText); ptr = strtok(temp.stringText, delimter_string); for (i = 0; i < nth_token; i++) if ((ptr = strtok(NULL, delimter_string)) == NULL) break; if (ptr == NULL) { CStringRepresentation null_return; return null_return; } CStringRepresentation token_return(ptr); return token_return; } #if 0 void CStringRepresentation::ToUpper() { Check(this); if (stringText != NULL) strupr(stringText); } void CStringRepresentation::ToLower() { Check(this); if (stringText != NULL) strlwr(stringText); } #endif MemoryStream& MemoryStream_Read(MemoryStream *stream, CStringRepresentation *str) { Check(stream); Check(str); size_t string_length; char *ptr; MemoryStream_Read(stream, &string_length); ptr = new char[string_length + 1]; Register_Pointer(ptr); stream->ReadBytes(ptr, string_length + 1); *str = ptr; Unregister_Pointer(ptr); delete[] ptr; Check(str); return *stream; } MemoryStream& MemoryStream_Write(MemoryStream *stream, const CStringRepresentation &str) { Check(stream); Check(&str); MemoryStream_Write(stream, &str.stringLength); return stream->WriteBytes(str.stringText, str.stringLength + 1); } void Convert_From_Ascii(const char *str, CStringRepresentation *value) { #if 0 Check_Pointer(str); Check(value); *value = str; #else if (str == NULL) Fail("Convert_From_Ascii - str == NULL"); if (value == NULL) Fail("Convert_From_Ascii - value == NULL"); *value = str; #endif } CString CString::operator = (const CString &str) { Check(this); Check(&str); if (this == &str) return *this; Check(representation); representation->DecrementReferenceCount(); representation = str.representation; representation->IncrementReferenceCount(); return *this; } CString CString::operator = (const char *cstr) { Check(representation); representation->DecrementReferenceCount(); representation = new CStringRepresentation(cstr); Register_Object(representation); representation->IncrementReferenceCount(); return *this; } MemoryStream& MemoryStream_Read(MemoryStream *stream, CString *str) { Check(str); Check(str->representation); str->representation->DecrementReferenceCount(); str->representation = new CStringRepresentation; Register_Object(str->representation); str->representation->IncrementReferenceCount(); Verify(str->representation->referenceCount == 1); return MemoryStream_Read(stream, str->representation); } void Convert_From_Ascii(const char *str, CString *value) { Check(value); Check(value->representation); value->representation->DecrementReferenceCount(); value->representation = new CStringRepresentation; Register_Object(value->representation); value->representation->IncrementReferenceCount(); Verify(value->representation->referenceCount == 1); Convert_From_Ascii(str, value->representation); } //} #if defined(TEST_CLASS) #include "cstr.tcp" #endif