XStr::XStr(const char* const toTranscode, MemoryManager *mm) : str_(0), mm_(mm) { if(toTranscode == 0) { str_ = mm_ ? (XMLCh*)mm_->allocate(1 * sizeof(XMLCh)) : new XMLCh[1]; str_[0] = 0; } else { XMLUTF8Transcoder t(0, 512); size_t l = XMLString::stringLen(toTranscode); const size_t needed = l * 2 + 1; // 2 chars per byte is the worst case, + '\0' str_ = mm_ ? (XMLCh*)mm_->allocate(needed * sizeof(XMLCh)) : new XMLCh[needed]; AutoDeleteArray<unsigned char> charSizes(new unsigned char[needed]); #if _XERCES_VERSION >= 30000 XMLSize_t bytesEaten = 0; t.transcodeFrom((const XMLByte*)toTranscode, l+1, str_, needed, bytesEaten, charSizes); #else unsigned int bytesEaten = 0; t.transcodeFrom((const XMLByte*)toTranscode, (unsigned int)l+1, str_, (unsigned int)needed, bytesEaten, charSizes); #endif } }
// --------------------------------------------------------------------------- // TranscodeFromStr: Private helper methods // --------------------------------------------------------------------------- void TranscodeFromStr::transcode(const XMLByte *in, XMLSize_t length, XMLTranscoder *trans) { if(!in) return; XMLSize_t allocSize = length + 1; fString = (XMLCh*)fMemoryManager->allocate(allocSize * sizeof(XMLCh)); ArrayJanitor<XMLCh> janString(fString, fMemoryManager); XMLSize_t csSize = allocSize; ArrayJanitor<unsigned char> charSizes((unsigned char*)fMemoryManager->allocate(csSize * sizeof(unsigned char)), fMemoryManager); XMLSize_t bytesDone = 0; while(bytesDone < length) { if ((allocSize - fCharsWritten) > csSize) { csSize = allocSize - fCharsWritten; charSizes.reset((unsigned char*)fMemoryManager->allocate(csSize * sizeof(unsigned char)), fMemoryManager); } XMLSize_t bytesRead = 0; fCharsWritten += trans->transcodeFrom(in + bytesDone, length - bytesDone, fString + fCharsWritten, allocSize - fCharsWritten, bytesRead, charSizes.get()); if(bytesRead == 0) ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, fMemoryManager); bytesDone += bytesRead; if (((allocSize - fCharsWritten)*sizeof(XMLCh)) < (length - bytesDone)) { allocSize *= 2; XMLCh *newBuf = (XMLCh*)fMemoryManager->allocate(allocSize * sizeof(XMLCh)); memcpy(newBuf, fString, fCharsWritten*sizeof(XMLCh)); fString = newBuf; janString.reset(fString, fMemoryManager); } } // null terminate if ((fCharsWritten + 1) > allocSize) { allocSize = fCharsWritten + 1; XMLCh *newBuf = (XMLCh*)fMemoryManager->allocate(allocSize * sizeof(XMLCh)); memcpy(newBuf, fString, fCharsWritten*sizeof(XMLCh)); fString = newBuf; janString.reset(fString, fMemoryManager); } fString[fCharsWritten] = 0; // Leave fString with ownership of the buffer janString.release(); }
// --------------------------------------------------------------------------- // TranscodeFromStr: Private helper methods // --------------------------------------------------------------------------- void TranscodeFromStr::transcode(const XMLByte *in, XMLSize_t length, XMLTranscoder *trans) { if(!in) return; XMLSize_t allocSize = length + 1; fString = (XMLCh*)fMemoryManager->allocate(allocSize * sizeof(XMLCh)); XMLSize_t csSize = length; ArrayJanitor<unsigned char> charSizes((unsigned char*)fMemoryManager->allocate(csSize * sizeof(unsigned char)), fMemoryManager); XMLSize_t bytesRead = 0; XMLSize_t bytesDone = 0; while(true) { fCharsWritten += trans->transcodeFrom(in + bytesDone, length - bytesDone, fString + fCharsWritten, allocSize - fCharsWritten, bytesRead, charSizes.get()); if(bytesRead == 0) ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, fMemoryManager); bytesDone += bytesRead; if(bytesDone == length) break; allocSize *= 2; XMLCh *newBuf = (XMLCh*)fMemoryManager->allocate(allocSize * sizeof(XMLCh)); memcpy(newBuf, fString, fCharsWritten); fMemoryManager->deallocate(fString); fString = newBuf; if((allocSize - fCharsWritten) > csSize) { csSize = allocSize - fCharsWritten; charSizes.reset((unsigned char*)fMemoryManager->allocate(csSize * sizeof(unsigned char)), fMemoryManager); } } // null terminate if(fCharsWritten == allocSize) { allocSize += 1; XMLCh *newBuf = (XMLCh*)fMemoryManager->allocate(allocSize * sizeof(XMLCh)); memcpy(newBuf, fString, fCharsWritten); fMemoryManager->deallocate(fString); fString = newBuf; } fString[fCharsWritten] = 0; }
const XMLCh *StringPool::getPooledString(const char *src) { if(src == 0) return 0; if(*src == 0) return XMLUni::fgZeroLenString; XMLCh *transcoded; { XMLUTF8Transcoder t(0, 512); size_t l = XMLString::stringLen(src); const size_t needed = l * 2 + 2; // 2 chars per byte is the worst case, + '\0' transcoded = (XMLCh*)_mm->allocate(needed); AutoDeleteArray<unsigned char> charSizes(new unsigned char[needed]); #if _XERCES_VERSION >= 30000 XMLSize_t bytesEaten = 0; t.transcodeFrom((const XMLByte*)src, l+1, transcoded, needed, bytesEaten, charSizes); #else unsigned int bytesEaten = 0; t.transcodeFrom((const XMLByte*)src, (unsigned int)l+1, transcoded, (unsigned int)needed, bytesEaten, charSizes); #endif } // strings longer than lengthThreshold bytes are not pooled, as it is not probable they can be recycled const XMLCh* pszTmp = transcoded + 1; while(*pszTmp) ++pszTmp; unsigned int length = (unsigned int)(pszTmp - transcoded); if(length > lengthThreshold) { ++_toobig; return transcoded; } unsigned int hashVal = hash(transcoded, length); unsigned int modHashVal = hashVal % _modulus; const Bucket *bucket = _bucketList[modHashVal]; while(bucket) { if(bucket->length == length && XPath2Utils::equals(bucket->value, transcoded)) { break; } bucket = bucket->next; } if(bucket) { ++_hits; _mm->deallocate(transcoded); return bucket->value; } else { ++_misses; if(_count >= (_modulus * 3 / 4)) { resize(); modHashVal = hashVal % _modulus; } _bucketList[modHashVal] = new (_mm->allocate(sizeof(Bucket))) Bucket(transcoded, length, hashVal, _bucketList[modHashVal]); ++_count; return transcoded; } }