📄 stafstring.cpp
字号:
/*****************************************************************************//* Software Testing Automation Framework (STAF) *//* (C) Copyright IBM Corp. 2001 *//* *//* This software is licensed under the Common Public License (CPL) V1.0. *//*****************************************************************************/#include "STAF.h"#include <map>#include <ctype.h>#include <string>#include "STAFString.h"#include "STAFMutexSem.h"#include "STAFConverter.h"#include "STAFUtil.h"#include "STAFTrace.h"////////////////////////////////////////////////////////////////////////////////// defined constantsconst unsigned int MIN = 32; // min alloc mem for stringsconst unsigned int MAX = 4096; // best if it's a page sizeconst unsigned int DELTA = 4096; // best if it's a page sizeconst unsigned int ISCHAR = 0; // corb (character or byte parm)const unsigned int ISBYTE = 1; // corb (character or byte parm)////////////////////////////////////////////////////////////////////////////////struct STAFStringImplementation{ char *pBuffer; unsigned int fBuffLen; unsigned int fCharLen; unsigned int fByteLen;};static const char SIZE_TABLE[] = { // This table allows for O(1) lookup of a char size. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0};static const STAFStringImplementation CHAR_TABLE[] ={ { "\x0", 1, 1, 1 }, { "\x20", 1, 1, 1 }, { "\x7b", 1, 1, 1 }, { "\x7d", 1, 1, 1 }, { "\x28", 1, 1, 1 }, { "\x29", 1, 1, 1 }, { "\x3c", 1, 1, 1 }, { "\x3e", 1, 1, 1 }, { "\x3a", 1, 1, 1 }, { "\x3b", 1, 1, 1 }, { "\x2c", 1, 1, 1 }, { "\x2e", 1, 1, 1 }, { "\x5c", 1, 1, 1 }, { "\x2f", 1, 1, 1 }, { "\x3d", 1, 1, 1 }, { "\x27", 1, 1, 1 }, { "\x22", 1, 1, 1 }, { "\x7c", 1, 1, 1 }, { "\xc0\x80", 2, 1, 2 }, { "\x23", 1, 1, 1 }, { "\x0d", 1, 1, 1 }, { "\x0a", 1, 1, 1 }, { "\x2a", 1, 1, 1 }, { "\x2d", 1, 1, 1 }, { "\x25", 1, 1, 1 }, { "\x3f", 1, 1, 1 }, { "\x5e", 1, 1, 1 }, { "\x26", 1, 1, 1 }, { "\x40", 1, 1, 1 }, { "\x09", 1, 1, 1 }, { "\x21", 1, 1, 1 }};static const char *EMPTY_STRING = "";////////////////////////////////////////////////////////////////////////////////// useful inline methods inline int BYTES(char *c) { return SIZE_TABLE[(unsigned char)*c]; }inline int SPACE(char *c) { return (*c == 0x20); }inline int DIGIT(char *c) { return (*c >= 0x30 && *c <= 0x39); }inline int ASCII(char *c) { return (BYTES(c) == 1); }inline int WHITESPACE(char *c) { return (*c == 0x20 || *c == 0x09 || *c == 0x0A || *c == 0x0D); }inline char *PREV(char *c) { while (!BYTES(--c)); return c; }inline char *NEXT(char *c) { c += BYTES(c); return c; }inline char *REWB(char *c, unsigned int n) { return c - n; }inline char *FWDB(char *c, unsigned int n) { return c + n; }inline char *REWC(char *c, unsigned int n) { while (n--) c = PREV(c); return c; }inline char *FWDC(char *c, unsigned int n) { while (n--) c = NEXT(c); return c; }inline char *REWN(char *c, unsigned int n, unsigned int corb) { return (corb ? REWB(c, n) : REWC(c, n)); }inline char *FWDN(char *c, unsigned int n, unsigned int corb) { return (corb ? FWDB(c, n) : FWDC(c, n)); }// Determine the size of the new buffer to allocate. // The new size will be at least MIN bytes and increases by powers// of 2 up to MAX bytes; after that, allocation is done in increments of// DELTA bytes.unsigned int getBufferSize(unsigned int len){ unsigned int min = MIN; // find the minimum storage for the string (a power of 2 < max) while (min < len && min < MAX) min <<= 1; // O(lg MAX) // if len is above the max mark, find what needs to be allocated in // delta increments, i.e. if diff == 5 then alloc min + diff * delta int diff = len - MAX; diff = (diff > 0 ? (diff / DELTA) + 1 : 0); return min + diff * DELTA;}////////////////////////////////////////////////////////////////////////////////static STAFConverter *sConverterPtr = 0;static STAFMutexSem sConverterSem;static const STAFString sStar(kUTF8_STAR);static const STAFString sQuestion(kUTF8_QUESTION);static const STAFString sWildCards(sStar + sQuestion);////////////////////////////////////////////////////////////////////////////////STAFRC_t STAFStringConstruct(STAFString_t *pString, const char *buffer, unsigned int len, unsigned int *osRC){ // This is the master constructor and is used by all other constructors. // this constructor allocates at least MIN bytes and increases by powers // of 2 up to MAX bytes; after that, allocation is done in increments of // DELTA bytes. // if buffer is 0 or len is 0, create an empty string if (pString == 0) return kSTAFInvalidObject;; *pString = new STAFStringImplementation; STAFStringImplementation &str = **pString; if (buffer == 0 || len == 0) { str.pBuffer = (char *)EMPTY_STRING; str.fBuffLen = 0; str.fCharLen = 0; str.fByteLen = 0; return kSTAFOk; } // Determine the size of the new buffer to allocate. str.fBuffLen = getBufferSize(len); str.pBuffer = new char[str.fBuffLen]; // copy string into buffer memcpy(str.pBuffer, buffer, len); // set byte length and compute char length of string str.fByteLen = len; // calculate the length of the string in chars str.fCharLen = 0; char *ptr = (char *)(buffer); char *lim = (char *)(buffer + len); while (ptr < lim) { str.fCharLen++; if (BYTES(ptr) == 0) { STAFTrace::trace(kSTAFTraceError, "STAFStringConstruct::Invalid UTF-8 data"); return kSTAFInvalidValue; } ptr = NEXT(ptr); } return kSTAFOk;}STAFRC_t STAFStringConstructCopy(STAFString_t *pString, STAFStringConst_t aString, unsigned int *osRC){ if (pString == 0) return kSTAFInvalidObject; if (aString == 0 || aString->fByteLen == 0) return STAFStringConstruct(pString, 0, 0, osRC); return STAFStringConstruct(pString, aString->pBuffer, aString->fByteLen, osRC);}STAFRC_t STAFStringConstructFromCurrentCodePage(STAFString_t *pString, const char *from, unsigned int len, unsigned int *osRC){ if (pString == 0) return kSTAFInvalidObject; if (from == 0 || len == 0) return STAFStringConstruct(pString, 0, 0, osRC); STAFRC_t rc = kSTAFOk; if (sConverterPtr == 0) { STAFMutexSemLock lock(sConverterSem); sConverterPtr = new STAFConverter(); } const unsigned int SIZE = 4096; const unsigned char *fromPtr = (unsigned char *)from; unsigned int fromLen = len; unsigned char *toPtr = new unsigned char[SIZE]; unsigned int toLen = SIZE; std::string result = ""; unsigned int resultLen = 0; // now let's actually do the conversion while (fromLen > 0) { int rc2 = sConverterPtr->convertToUTF8(&fromPtr, &fromLen, toPtr, &toLen); if (rc2) { delete[] toPtr; if (osRC) *osRC = 0; return kSTAFConverterError; } result += std::string((char *)toPtr, toLen); resultLen += toLen; toLen = SIZE; } delete[] toPtr; return STAFStringConstruct(pString, result.data(), resultLen, osRC);}STAFRC_t STAFStringConstructFromUInt(STAFString_t *pString, unsigned int value, unsigned int base, unsigned int *osRC){ if (pString == 0) return kSTAFInvalidObject; if (base == 0 || base > 16) return kSTAFInvalidParm; // this buffer is used to create the string equivalent of value, // which ends up right justified. then we pass that to the cons- // tructor char buffer[32]; char *ptr = &buffer[31]; unsigned int len = 0; do { if ((*ptr = (value % base) + 0x30) > 0x39) *ptr += 7; ptr--; len++; } while (value /= base); ptr++; // adjust ptr to begin of string return STAFStringConstruct(pString, ptr, len, osRC);}STAFRC_t STAFStringConstructSubString(STAFString_t *pSubStr, STAFStringConst_t aString, unsigned int index, unsigned int len, unsigned int corb, unsigned int *osRC){ if (pSubStr == 0) return kSTAFInvalidObject; if (aString == 0 || aString->fByteLen == 0) return STAFStringConstruct(pSubStr, 0, 0, osRC); char *ptr = aString->pBuffer; char *lim = aString->pBuffer + aString->fByteLen; // if index is beyond string's length, return empty string if (index >= (corb ? aString->fByteLen : aString->fCharLen)) return STAFStringConstruct(pSubStr, 0, 0, osRC); ptr = FWDN(ptr, index, corb); // if len is beyond string's length - index, return rest of string if (len < (corb ? aString->fByteLen : aString->fCharLen) - index) lim = FWDN(ptr, len, corb); return STAFStringConstruct(pSubStr, ptr, lim - ptr, osRC);}STAFRC_t STAFStringConstructSubWord(STAFString_t *pWord, STAFStringConst_t aString, unsigned int index, unsigned int count, unsigned int *osRC){ char *ptr = 0; char *lim = 0; char *str = 0; char *end = 0; if (pWord == 0) return kSTAFInvalidObject; if (aString == 0) return kSTAFInvalidParm; ptr = aString->pBuffer; lim = aString->pBuffer + aString->fByteLen; while (ptr < lim && WHITESPACE(ptr)) { ptr = NEXT(ptr); } if (ptr >= lim) { return STAFStringConstruct(pWord, 0, 0, osRC); } str = ptr; end = PREV(lim); while (end >= str && WHITESPACE(end)) { end = PREV(end); } if (end < str) { return STAFStringConstruct(pWord, 0, 0, osRC); } end = NEXT(end); while (ptr < end && index--) { while (ptr < end && WHITESPACE(ptr)) { ptr = NEXT(ptr); } if (ptr >= end) { break; } while (ptr < end && !WHITESPACE(ptr)) { ptr = NEXT(ptr); } if (ptr >= end) { break; } while (ptr < end && WHITESPACE(ptr)) { ptr = NEXT(ptr); } } str = ptr; while (ptr < end && count--) { while (ptr < end && WHITESPACE(ptr)) { ptr = NEXT(ptr); } if (ptr >= end) { break; } while (ptr < end && !WHITESPACE(ptr)) { ptr = NEXT(ptr); } } end = ptr; return STAFStringConstruct(pWord, str, end - str, osRC);}STAFRC_t STAFStringConstructChar(STAFString_t *pChar, STAFUTF8Char_t aChar, unsigned int *osRC){ if (pChar == 0) return kSTAFInvalidObject; return STAFStringConstructCopy(pChar, &CHAR_TABLE[aChar], osRC);}STAFRC_t STAFStringConstructJoin(STAFString_t *pString, STAFString_t aStringArray[], unsigned int arraySize, unsigned int *osRC){ if (pString == 0) return kSTAFInvalidObject; *pString = new STAFStringImplementation;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -