in src/dxapi/native/tickdb/data_writer.cpp [622:685]
template<typename T, typename CHARTYPE> INLINE void DataWriterInternal::putAlphanumeric(uint32 fieldSize, const CHARTYPE *str, size_t stringLength)
{
if (stringLength > fieldSize) {
THROW_DBGLOG("Alphanumeric field is too long");
}
size_t nSizeBits = _bsr(++fieldSize);
if (NULL == str) {
putBE<uint32>(fieldSize << (32 - nSizeBits), (nSizeBits + 7) >> 3);
return;
}
if (stringLength > fieldSize) {
THROW_DBGLOG("writeAlphanumeric(): String is too long!");
}
if (0 == stringLength) {
putLE<uint32>(0, (nSizeBits + 7) >> 3);
setNotNull();
return;
}
assert(nSizeBits + 6 <= BITSIZEOF(T));
// TODO: ensure T is unsigned
T accumulator = stringLength;// << 6;
int nBitsFree = (int)(BITSIZEOF(T) - nSizeBits);
intptr nCharsRemaining = -(intptr)stringLength;
str += stringLength;
typedef typename make_unsigned<CHARTYPE>::type UCHARTYPE;
do {
unsigned ch;
// Reserve space in the accumulator (6 more bits)
if ((nBitsFree -= 6) < 0) {
// We should never get here if the whole value fits into T (10 chars if T=uint64)
// Write sizeof(T) - 1 bytes
#if 0
// Version 1
// we store (sizeof(T) - 1) completely filled bytes and adjust the number of free bits accordingly
putBE<T>(accumulator << (nBitsFree + 6), sizeof(T) - 1);
nBitsFree += (sizeof(T) - 1) * 8;
#else
// Version 2
putBE<T>((accumulator << (nBitsFree + 6)) | (ch >> -nBitsFree), sizeof(T));
nBitsFree += BITSIZEOF(T); // possible values:
accumulator = 0; // Redundant, actually
#endif
}
ch = (UCHARTYPE)str[nCharsRemaining] - (unsigned)' ';
if (ch >= 0x40 /*ch & -0x40 */) {
THROW_DBGLOG("writeAlphanumeric(): Invalid character encountered: 0x%02x = '%c'", (unsigned)ch, (unsigned)ch);
}
accumulator = (accumulator << 6) | ch;
} while (0 != ++nCharsRemaining);
assert(nBitsFree < BITSIZEOF(T)); // At least 1 bit must be used
// Finally write the number of bytes necessary to hold these remaining bits
putBE<T>(accumulator << nBitsFree, (BITSIZEOF(T) + 7 - nBitsFree) >> 3);
setNotNull();
}