1
0
Fork 0
arangodb/Basics/StringBuffer.h

1015 lines
39 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// @brief string buffer with formatting routines
///
/// @file
///
/// @warning You must initialise the classes by calling initialise or by
/// setting everything to 0. This can be done by using "new
/// StringBuffer()". You must call free to free the allocated
/// memory.
///
/// WARNING: this must be a POD object!
///
/// DISCLAIMER
///
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2006-2011, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_JUTLAND_BASICS_STRING_BUFFER_H
#define TRIAGENS_JUTLAND_BASICS_STRING_BUFFER_H 1
#include <Basics/Common.h>
// -----------------------------------------------------------------------------
// string buffer with formatting routines
// -----------------------------------------------------------------------------
#ifdef STRING_BUFFER_MACROS
#define DEFSTR(a,b) static const char __STRING_ ## a [] = b
#define STR(a) __STRING_ ## a
#define LENSTR(a) (sizeof(__STRING_ ## a) - 1)
#endif
namespace triagens {
namespace basics {
////////////////////////////////////////////////////////////////////////////////
/// @ingroup Utilities
/// @brief string buffer with formatting routines
////////////////////////////////////////////////////////////////////////////////
struct StringBuffer {
// -----------------------------------------------------------------------------
// constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief initialises the string buffer
///
/// This method is implemented here in order to allow inlining.
///
/// @warning You must call initialise before using the string buffer.
////////////////////////////////////////////////////////////////////////////////
void initialise () {
buffer = 0;
bufferPtr = 0;
bufferEnd = 0;
reserve(1);
*bufferPtr = 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief frees the string buffer
///
/// This method is implemented here in order to allow inlining.
///
/// @warning You must call free after using the string buffer.
////////////////////////////////////////////////////////////////////////////////
void free () {
if (buffer != 0) {
delete[] buffer;
buffer = 0;
bufferPtr = 0;
bufferEnd = 0;
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief frees the string buffer and cleans the buffer
///
/// This method is implemented here in order to allow inlining.
///
/// @warning You must call free after using the string buffer.
////////////////////////////////////////////////////////////////////////////////
void destroy () {
if (buffer != 0) {
memset(buffer, 0, bufferEnd - buffer);
delete[] buffer;
buffer = 0;
bufferPtr = 0;
bufferEnd = 0;
}
}
// -----------------------------------------------------------------------------
// public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief swaps content with another string buffer
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void swap (StringBuffer * other) {
char * otherBuffer = other->buffer;
char * otherBufferPtr = other->bufferPtr;
char * otherBufferEnd = other->bufferEnd;
other->buffer = buffer;
other->bufferPtr = bufferPtr;
other->bufferEnd = bufferEnd;
buffer = otherBuffer;
bufferPtr = otherBufferPtr;
bufferEnd = otherBufferEnd;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns pointer to the character buffer
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
const char * c_str () const {
return buffer;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns pointer to the beginning of the character buffer
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
const char * begin () const {
return buffer;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns pointer to the end of the character buffer
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
const char * end () const {
return bufferPtr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns length of the character buffer
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
size_t length () const {
return bufferPtr - buffer;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns true if buffer is empty
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
bool empty () const {
return bufferPtr == buffer;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief clears the buffer
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void clear () {
bufferPtr = buffer;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief assigns text from a string
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
StringBuffer& operator= (string const& str) {
replaceText(str.c_str(), str.length());
return *this;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief copies the string buffer
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void copy (StringBuffer const& source) {
replaceText(source.c_str(), source.length());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief removes the first characters
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void erase_front (size_t len) {
if (length() <= len) {
clear();
}
else if (0 < len) {
memmove(buffer, buffer + len, bufferPtr - buffer - len);
bufferPtr -= len;
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief replaces characters
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void replaceText (const char * str, size_t len) {
clear();
appendText(str, len);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief replaces characters
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void replaceText (StringBuffer const& text) {
clear();
appendText(text.c_str(), text.length());
}
// -----------------------------------------------------------------------------
// appenders
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief appends eol character
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendEol () {
appendChar('\n');
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends character
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendChar (char chr) {
reserve(2);
*bufferPtr++ = chr;
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends characters
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendText (const char * str, size_t len) {
if (len == 0) {
reserve(1);
*bufferPtr = '\0';
}
else {
reserve(len + 1);
memcpy(bufferPtr, str, len);
bufferPtr += len;
*bufferPtr = '\0';
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends characters
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendText (const char * str) {
size_t len = strlen(str);
reserve(len + 1);
memcpy(bufferPtr, str, len);
bufferPtr += len;
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends string
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendText (string const& str) {
appendText(str.c_str(), str.length());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends a string buffer
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendText (StringBuffer const& text) {
appendText(text.c_str(), text.length());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends integer with two digits
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendInteger2 (uint32_t attr) {
reserve(3);
appendChar0(char((attr / 10U) % 10 + '0'));
appendChar0(char( attr % 10 + '0'));
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends integer with three digits
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendInteger3 (uint32_t attr) {
reserve(4);
appendChar0(char((attr / 100U) % 10 + '0'));
appendChar0(char((attr / 10U) % 10 + '0'));
appendChar0(char( attr % 10 + '0'));
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends integer with four digits
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendInteger4 (uint32_t attr) {
reserve(5);
appendChar0(char((attr / 1000U) % 10 + '0'));
appendChar0(char((attr / 100U) % 10 + '0'));
appendChar0(char((attr / 10U) % 10 + '0'));
appendChar0(char( attr % 10 + '0'));
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends integer with 8 bits
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendInteger (int8_t attr) {
if (attr == INT8_MIN) {
appendText("-128", 4);
return;
}
reserve(5);
if (attr < 0) {
appendChar0('-');
attr = -attr;
}
if (100 <= attr) { appendChar0((attr / 100) % 10 + '0'); }
if ( 10 <= attr) { appendChar0((attr / 10) % 10 + '0'); }
appendChar0(char(attr % 10 + '0'));
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends unsigned integer with 8 bits
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendInteger (uint8_t attr) {
reserve(4);
if (100U <= attr) { appendChar0((attr / 100U) % 10 + '0'); }
if ( 10U <= attr) { appendChar0((attr / 10U) % 10 + '0'); }
appendChar0(char(attr % 10 + '0'));
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends integer with 16 bits
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendInteger (int16_t attr) {
if (attr == INT16_MIN) {
appendText("-32768", 6);
return;
}
reserve(7);
if (attr < 0) {
appendChar0('-');
attr = -attr;
}
if (10000 <= attr) { appendChar0(char((attr / 10000) % 10 + '0')); }
if ( 1000 <= attr) { appendChar0(char((attr / 1000) % 10 + '0')); }
if ( 100 <= attr) { appendChar0(char((attr / 100) % 10 + '0')); }
if ( 10 <= attr) { appendChar0(char((attr / 10) % 10 + '0')); }
appendChar0(char(attr % 10 + '0'));
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends unsigned integer with 32 bits
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendInteger (uint16_t attr) {
reserve(6);
if (10000U <= attr) { appendChar0(char((attr / 10000U) % 10 + '0')); }
if ( 1000U <= attr) { appendChar0(char((attr / 1000U) % 10 + '0')); }
if ( 100U <= attr) { appendChar0(char((attr / 100U) % 10 + '0')); }
if ( 10U <= attr) { appendChar0(char((attr / 10U) % 10 + '0')); }
appendChar0(char(attr % 10 + '0'));
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends integer with 32 bits
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendInteger (int32_t attr) {
if (attr == INT32_MIN) {
appendText("-2147483648", 11);
return;
}
reserve(12);
if (attr < 0) {
appendChar0('-');
attr = -attr;
}
if (1000000000 <= attr) { appendChar0(char((attr / 1000000000) % 10 + '0')); }
if ( 100000000 <= attr) { appendChar0(char((attr / 100000000) % 10 + '0')); }
if ( 10000000 <= attr) { appendChar0(char((attr / 10000000) % 10 + '0')); }
if ( 1000000 <= attr) { appendChar0(char((attr / 1000000) % 10 + '0')); }
if ( 100000 <= attr) { appendChar0(char((attr / 100000) % 10 + '0')); }
if ( 10000 <= attr) { appendChar0(char((attr / 10000) % 10 + '0')); }
if ( 1000 <= attr) { appendChar0(char((attr / 1000) % 10 + '0')); }
if ( 100 <= attr) { appendChar0(char((attr / 100) % 10 + '0')); }
if ( 10 <= attr) { appendChar0(char((attr / 10) % 10 + '0')); }
appendChar0(char(attr % 10 + '0'));
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends unsigned integer with 32 bits
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendInteger (uint32_t attr) {
reserve(11);
if (1000000000U <= attr) { appendChar0(char((attr / 1000000000U) % 10 + '0')); }
if ( 100000000U <= attr) { appendChar0(char((attr / 100000000U) % 10 + '0')); }
if ( 10000000U <= attr) { appendChar0(char((attr / 10000000U) % 10 + '0')); }
if ( 1000000U <= attr) { appendChar0(char((attr / 1000000U) % 10 + '0')); }
if ( 100000U <= attr) { appendChar0(char((attr / 100000U) % 10 + '0')); }
if ( 10000U <= attr) { appendChar0(char((attr / 10000U) % 10 + '0')); }
if ( 1000U <= attr) { appendChar0(char((attr / 1000U) % 10 + '0')); }
if ( 100U <= attr) { appendChar0(char((attr / 100U) % 10 + '0')); }
if ( 10U <= attr) { appendChar0(char((attr / 10U) % 10 + '0')); }
appendChar0(char(attr % 10 + '0'));
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends integer with 64 bits
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendInteger (int64_t attr) {
if (attr == INT64_MIN) {
appendText("-9223372036854775808", 20);
return;
}
else if (attr < 0) {
reserve(1);
appendChar0('-');
attr = -attr;
}
if ((attr >> 32) == 0) {
appendInteger(uint32_t(attr));
return;
}
reserve(20);
// uint64_t has one more decimal than int64_t
if (1000000000000000000LL <= attr) { appendChar0(char((attr / 1000000000000000000LL) % 10 + '0')); }
if ( 100000000000000000LL <= attr) { appendChar0(char((attr / 100000000000000000LL) % 10 + '0')); }
if ( 10000000000000000LL <= attr) { appendChar0(char((attr / 10000000000000000LL) % 10 + '0')); }
if ( 1000000000000000LL <= attr) { appendChar0(char((attr / 1000000000000000LL) % 10 + '0')); }
if ( 100000000000000LL <= attr) { appendChar0(char((attr / 100000000000000LL) % 10 + '0')); }
if ( 10000000000000LL <= attr) { appendChar0(char((attr / 10000000000000LL) % 10 + '0')); }
if ( 1000000000000LL <= attr) { appendChar0(char((attr / 1000000000000LL) % 10 + '0')); }
if ( 100000000000LL <= attr) { appendChar0(char((attr / 100000000000LL) % 10 + '0')); }
if ( 10000000000LL <= attr) { appendChar0(char((attr / 10000000000LL) % 10 + '0')); }
if ( 1000000000LL <= attr) { appendChar0(char((attr / 1000000000LL) % 10 + '0')); }
if ( 100000000LL <= attr) { appendChar0(char((attr / 100000000LL) % 10 + '0')); }
if ( 10000000LL <= attr) { appendChar0(char((attr / 10000000LL) % 10 + '0')); }
if ( 1000000LL <= attr) { appendChar0(char((attr / 1000000LL) % 10 + '0')); }
if ( 100000LL <= attr) { appendChar0(char((attr / 100000LL) % 10 + '0')); }
if ( 10000LL <= attr) { appendChar0(char((attr / 10000LL) % 10 + '0')); }
if ( 1000LL <= attr) { appendChar0(char((attr / 1000LL) % 10 + '0')); }
if ( 100LL <= attr) { appendChar0(char((attr / 100LL) % 10 + '0')); }
if ( 10LL <= attr) { appendChar0(char((attr / 10LL) % 10 + '0')); }
appendChar0(char(attr % 10 + '0'));
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends unsigned integer with 64 bits
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendInteger (uint64_t attr) {
if ((attr >> 32) == 0) {
appendInteger(uint32_t(attr));
return;
}
reserve(21);
// uint64_t has one more decimal than int64_t
if (10000000000000000000ULL <= attr) { appendChar0(char((attr / 10000000000000000000ULL) % 10 + '0')); }
if ( 1000000000000000000ULL <= attr) { appendChar0(char((attr / 1000000000000000000ULL) % 10 + '0')); }
if ( 100000000000000000ULL <= attr) { appendChar0(char((attr / 100000000000000000ULL) % 10 + '0')); }
if ( 10000000000000000ULL <= attr) { appendChar0(char((attr / 10000000000000000ULL) % 10 + '0')); }
if ( 1000000000000000ULL <= attr) { appendChar0(char((attr / 1000000000000000ULL) % 10 + '0')); }
if ( 100000000000000ULL <= attr) { appendChar0(char((attr / 100000000000000ULL) % 10 + '0')); }
if ( 10000000000000ULL <= attr) { appendChar0(char((attr / 10000000000000ULL) % 10 + '0')); }
if ( 1000000000000ULL <= attr) { appendChar0(char((attr / 1000000000000ULL) % 10 + '0')); }
if ( 100000000000ULL <= attr) { appendChar0(char((attr / 100000000000ULL) % 10 + '0')); }
if ( 10000000000ULL <= attr) { appendChar0(char((attr / 10000000000ULL) % 10 + '0')); }
if ( 1000000000ULL <= attr) { appendChar0(char((attr / 1000000000ULL) % 10 + '0')); }
if ( 100000000ULL <= attr) { appendChar0(char((attr / 100000000ULL) % 10 + '0')); }
if ( 10000000ULL <= attr) { appendChar0(char((attr / 10000000ULL) % 10 + '0')); }
if ( 1000000ULL <= attr) { appendChar0(char((attr / 1000000ULL) % 10 + '0')); }
if ( 100000ULL <= attr) { appendChar0(char((attr / 100000ULL) % 10 + '0')); }
if ( 10000ULL <= attr) { appendChar0(char((attr / 10000ULL) % 10 + '0')); }
if ( 1000ULL <= attr) { appendChar0(char((attr / 1000ULL) % 10 + '0')); }
if ( 100ULL <= attr) { appendChar0(char((attr / 100ULL) % 10 + '0')); }
if ( 10ULL <= attr) { appendChar0(char((attr / 10ULL) % 10 + '0')); }
appendChar0(char(attr % 10 + '0'));
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends size_t
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_OVERLOAD_FUNCS_SIZE_T
void appendInteger (size_t attr) {
appendInteger(sizetint_t(attr));
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief appends unsigned integer with 32 bits in octal
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendOctal (uint32_t attr) {
reserve(9);
if (010000000U <= attr) { appendChar0(char((attr / 010000000U) % 010 + '0')); }
if ( 01000000U <= attr) { appendChar0(char((attr / 01000000U) % 010 + '0')); }
if ( 0100000U <= attr) { appendChar0(char((attr / 0100000U) % 010 + '0')); }
if ( 010000U <= attr) { appendChar0(char((attr / 010000U) % 010 + '0')); }
if ( 01000U <= attr) { appendChar0(char((attr / 01000U) % 010 + '0')); }
if ( 0100U <= attr) { appendChar0(char((attr / 0100U) % 010 + '0')); }
if ( 010U <= attr) { appendChar0(char((attr / 010U) % 010 + '0')); }
appendChar0(char(attr % 010 + '0'));
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends unsigned integer with 64 bits in octal
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendOctal (uint64_t attr) {
reserve(17);
if (01000000000000000ULL <= attr) { appendChar0(char((attr / 01000000000000000ULL) % 010 + '0')); }
if ( 0100000000000000ULL <= attr) { appendChar0(char((attr / 0100000000000000ULL) % 010 + '0')); }
if ( 010000000000000ULL <= attr) { appendChar0(char((attr / 010000000000000ULL) % 010 + '0')); }
if ( 01000000000000ULL <= attr) { appendChar0(char((attr / 01000000000000ULL) % 010 + '0')); }
if ( 0100000000000ULL <= attr) { appendChar0(char((attr / 0100000000000ULL) % 010 + '0')); }
if ( 010000000000ULL <= attr) { appendChar0(char((attr / 010000000000ULL) % 010 + '0')); }
if ( 01000000000ULL <= attr) { appendChar0(char((attr / 01000000000ULL) % 010 + '0')); }
if ( 0100000000ULL <= attr) { appendChar0(char((attr / 0100000000ULL) % 010 + '0')); }
if ( 010000000ULL <= attr) { appendChar0(char((attr / 010000000ULL) % 010 + '0')); }
if ( 01000000ULL <= attr) { appendChar0(char((attr / 01000000ULL) % 010 + '0')); }
if ( 0100000ULL <= attr) { appendChar0(char((attr / 0100000ULL) % 010 + '0')); }
if ( 010000ULL <= attr) { appendChar0(char((attr / 010000ULL) % 010 + '0')); }
if ( 01000ULL <= attr) { appendChar0(char((attr / 01000ULL) % 010 + '0')); }
if ( 0100ULL <= attr) { appendChar0(char((attr / 0100ULL) % 010 + '0')); }
if ( 010ULL <= attr) { appendChar0(char((attr / 010ULL) % 010 + '0')); }
appendChar0(char(attr % 010 + '0'));
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends size_t in octal
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_OVERLOAD_FUNCS_SIZE_T
void appendOctal (size_t attr) {
appendOctal(sizetint_t(attr));
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief appends unsigned integer with 32 bits in hex
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendHex (uint32_t attr) {
static char const * const HEX = "0123456789ABCDEF";
reserve(5);
if (0x1000U <= attr) { appendChar0(HEX[(attr / 0x1000U) % 0x10]); }
if ( 0x100U <= attr) { appendChar0(HEX[(attr / 0x100U) % 0x10]); }
if ( 0x10U <= attr) { appendChar0(HEX[(attr / 0x10U) % 0x10]); }
appendChar0(HEX[attr % 0x10]);
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends unsigned integer with 64 bits in hex
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendHex (uint64_t attr) {
static char const * const HEX = "0123456789ABCDEF";
reserve(9);
if (0x10000000U <= attr) { appendChar0(HEX[(attr / 0x10000000U) % 0x10]); }
if ( 0x1000000U <= attr) { appendChar0(HEX[(attr / 0x1000000U) % 0x10]); }
if ( 0x100000U <= attr) { appendChar0(HEX[(attr / 0x100000U) % 0x10]); }
if ( 0x10000U <= attr) { appendChar0(HEX[(attr / 0x10000U) % 0x10]); }
if ( 0x1000U <= attr) { appendChar0(HEX[(attr / 0x1000U) % 0x10]); }
if ( 0x100U <= attr) { appendChar0(HEX[(attr / 0x100U) % 0x10]); }
if ( 0x10U <= attr) { appendChar0(HEX[(attr / 0x10U) % 0x10]); }
appendChar0(HEX[attr % 0x10]);
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends size_t in hex
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_OVERLOAD_FUNCS_SIZE_T
void appendHex (size_t attr) {
appendHex(sizetint_t(attr));
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief appends floating point number with 8 bits
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendDecimal (double attr) {
reserve(1);
if (attr < 0.0) {
appendChar0('-');
attr = -attr;
}
else if (attr == 0.0) {
appendChar0('0');
*bufferPtr = '\0';
return;
}
if (double(uint32_t(attr)) == attr) {
appendInteger(uint32_t(attr));
return;
}
else if (attr < double(429496U)) {
uint32_t smll = uint32_t(attr * 10000.0);
if (double(smll) == attr * 10000.0) {
uint32_t exp = smll % 10000;
appendInteger(smll / 10000);
if (exp != 0) {
reserve(6);
appendChar0('.');
size_t pos = 0;
if ((exp / 1000L) % 10 != 0) pos = 1;
char a1 = char((exp / 1000L) % 10 + '0');
if ((exp / 100L) % 10 != 0) pos = 2;
char a2 = char((exp / 100L) % 10 + '0');
if ((exp / 10L) % 10 != 0) pos = 3;
char a3 = char((exp / 10L) % 10 + '0');
if (exp % 10 != 0) pos = 4;
char a4 = char(exp % 10 + '0');
appendChar0(a1);
if (pos > 1) { appendChar0(a2); }
if (pos > 2) { appendChar0(a3); }
if (pos > 3) { appendChar0(a4); }
*bufferPtr = '\0';
}
return;
}
}
// we do not habe a small integral number nor small decimal number with only a few decimal digits
// there at most 16 significant digits, first find out if we have an integer value
if (10000000000000000.0 < attr) {
size_t n = 0;
while (10000000000000000.0 < attr) {
attr /= 10.0;
++n;
}
appendInteger((uint64_t) attr);
reserve(n);
for (; 0 < n; --n) {
appendChar0('0');
}
*bufferPtr = '\0';
return;
}
// very small, i. e. less than 1
else if (attr < 1.0) {
size_t n = 0;
while (attr < 1.0) {
attr *= 10.0;
++n;
// should not happen, so it must be almost 0
if (n > 400) {
appendInteger(0);
return;
}
}
reserve(n + 2);
appendChar0('0');
appendChar0('.');
for (--n; 0 < n; --n) {
appendChar0('0');
}
attr = 10000000000000000.0 * attr;
appendInteger((uint64_t) attr);
return;
}
// somewhere in between
else {
uint64_t m = uint64_t(attr);
double d = attr - m;
appendInteger(m);
size_t n = 0;
while (d < 1.0) {
d *= 10.0;
++n;
// should not happen, so it must be almost 0
if (n > 400) {
return;
}
}
reserve(n + 1);
appendChar0('.');
for (--n; 0 < n; --n) {
appendChar0('0');
}
d = 10000000000000000.0 * d;
appendInteger((uint64_t) d);
return;
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends time in standard format
///
/// This method is implemented here in order to allow inlining.
////////////////////////////////////////////////////////////////////////////////
void appendTime (int32_t attr) {
int hour = attr / 3600;
int minute = (attr / 60) % 60;
int second = attr % 60;
reserve(9);
appendInteger2(hour);
appendChar(':');
appendInteger2(minute);
appendChar(':');
appendInteger2(second);
*bufferPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends csv string
////////////////////////////////////////////////////////////////////////////////
void appendCsvString (string const& text) {
// do not escape here, because some string - i.e. lists of identifier - have no special characters
appendText(text);
appendChar(';');
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends csv integer
////////////////////////////////////////////////////////////////////////////////
void appendCsvInteger (int32_t i) {
appendInteger(i);
appendChar(';');
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends csv integer
////////////////////////////////////////////////////////////////////////////////
void appendCsvInteger (uint32_t i) {
appendInteger(i);
appendChar(';');
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends csv integer
////////////////////////////////////////////////////////////////////////////////
void appendCsvInteger (uint64_t i) {
appendInteger(i);
appendChar(';');
}
////////////////////////////////////////////////////////////////////////////////
/// @brief appends csv double
////////////////////////////////////////////////////////////////////////////////
void appendCsvDouble (double d) {
appendDecimal(d);
appendChar(';');
}
// -----------------------------------------------------------------------------
// private methods
// -----------------------------------------------------------------------------
// private
void appendChar0 (char chr) {
*bufferPtr++ = chr;
}
void reserve (size_t size) {
if (buffer == 0) {
buffer = new char[size + 1];
bufferPtr = buffer;
bufferEnd = buffer + size;
}
else if (size_t(bufferEnd - bufferPtr) < size) {
size_t newlen = size_t(1.2 * ((bufferEnd - buffer) + size));
char * b = new char[newlen + 1];
memcpy(b, buffer, bufferEnd - buffer + 1);
delete[] buffer;
bufferPtr = b + (bufferPtr - buffer);
bufferEnd = b + newlen;
buffer = b;
}
}
// -----------------------------------------------------------------------------
// private data
// -----------------------------------------------------------------------------
char * buffer;
char * bufferPtr;
char * bufferEnd;
};
}
}
#endif