michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* vim:set ts=4 sw=4 sts=4 et cindent: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* We would use std::max but MS makes it painful michael@0: // windef.h defines min and max macros that we don't want michael@0: // http://support.microsoft.com/kb/143208 michael@0: #ifdef _WIN32 michael@0: #define NOMINMAX michael@0: #endif michael@0: */ michael@0: michael@0: #include michael@0: #include michael@0: #include "nsAlgorithm.h" michael@0: michael@0: /* This is a standard string builder like ones in Java michael@0: or C#. It uses a doubling allocation strategy michael@0: to grow when out of capacity. michael@0: michael@0: This does not use nsTArray because nsTArray starts michael@0: growing by multiples of page size after it is the michael@0: size of one page. We want to keep doubling in size michael@0: so that we can continue to append at high speed even michael@0: for large strings. michael@0: michael@0: Eventually, this should be templated for wide characters. michael@0: michael@0: */ michael@0: michael@0: namespace mozilla { michael@0: michael@0: class StringBuilder michael@0: { michael@0: public: michael@0: StringBuilder() { michael@0: mCapacity = 16; michael@0: mLength = 0; michael@0: mBuffer = static_cast(malloc(sizeof(char)*mCapacity)); michael@0: mBuffer[0] = '\0'; michael@0: } michael@0: michael@0: void Append(const char *s) { michael@0: size_t newLength = strlen(s); michael@0: michael@0: EnsureCapacity(mLength + newLength+1); michael@0: michael@0: // copy the entire string including the null terminator michael@0: memcpy(&mBuffer[mLength], s, newLength+1); michael@0: mLength += newLength; michael@0: } michael@0: michael@0: char *Buffer() { michael@0: return mBuffer; michael@0: } michael@0: michael@0: size_t Length() { michael@0: return mLength; michael@0: } michael@0: michael@0: size_t EnsureCapacity(size_t capacity) { michael@0: if (capacity > mCapacity) { michael@0: // make sure we at least double in size michael@0: mCapacity = XPCOM_MAX(capacity, mCapacity*2); michael@0: mBuffer = static_cast(realloc(mBuffer, mCapacity)); michael@0: mCapacity = moz_malloc_usable_size(mBuffer); michael@0: } michael@0: return mCapacity; michael@0: } michael@0: michael@0: ~StringBuilder() michael@0: { michael@0: free(mBuffer); michael@0: } michael@0: michael@0: private: michael@0: char *mBuffer; michael@0: size_t mLength; // the length of the contained string not including the null terminator michael@0: size_t mCapacity; // the total size of mBuffer michael@0: }; michael@0: michael@0: }