00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "Basics.H"
00029 #include "Text.H"
00030
00031
00032 static const char* const EmptyStr = "";
00033
00034 static const char *StrCopy(const char *str) throw ()
00035
00036 {
00037 int len = strlen(str) + 1;
00038 char *res = NEW_PTRFREE_ARRAY(char, len);
00039 memcpy(res, str, len);
00040 return res;
00041 }
00042
00043 static const char *StrCopy(const char *s, int len) throw ()
00044
00045
00046
00047 {
00048 char *res = NEW_PTRFREE_ARRAY(char, len+1);
00049 memcpy(res, s, len);
00050 res[len] = '\0';
00051 return res;
00052 }
00053
00054
00055 Text::Text() throw ()
00056 {
00057 this->s = EmptyStr;
00058 }
00059
00060 Text::Text(const char *str, void *copy) throw ()
00061 {
00062 this->s = (copy == (void *)NULL) ? StrCopy(str) : str;
00063 }
00064
00065 Text::Text(const char *bytes, int len) throw ()
00066 {
00067 this->s = StrCopy(bytes, len);
00068 }
00069
00070 Text::Text(const std::string &str) throw()
00071 {
00072 this->s = StrCopy(str.c_str());
00073 }
00074
00075 Text Text::Sub(int start, int len) const throw ()
00076 {
00077 int tLen = Length();
00078 Text res;
00079 if (start >= tLen || len == 0) {
00080 res.s = EmptyStr;
00081 } else {
00082 if ((unsigned int)start + (unsigned int)len > tLen) {
00083
00084 len = tLen - start + 1;
00085 char *temp = NEW_PTRFREE_ARRAY(char, len);
00086 memcpy(temp, this->s + start, len);
00087 res.s = temp;
00088 } else {
00089
00090 char *temp = NEW_PTRFREE_ARRAY(char, len+1);
00091 memcpy(temp, this->s + start, len);
00092 temp[len] = '\0';
00093 res.s = temp;
00094 }
00095 }
00096 return res;
00097 }
00098
00099 int Text::FindChar(char c, int start) const throw ()
00100 {
00101 int tLen = Length();
00102 for (register int i = max(start, 0); i < tLen; i++) {
00103 if (this->s[i] == c) return i;
00104 }
00105 return -1;
00106 }
00107
00108 int Text::FindCharR(char c, int start) const throw ()
00109 {
00110 int tLen = Length();
00111 for (register int i = min(start, tLen - 1); i >= 0; i--) {
00112 if (this->s[i] == c) return i;
00113 }
00114 return -1;
00115 }
00116
00117 int Text::FindText(const Text &substr, int start) const throw ()
00118 {
00119 start = max(start, 0);
00120 if (start + substr.Length() > this->Length()) return -1;
00121 char *match = strstr(this->s + start, substr.s);
00122 if (match != (char *)NULL) return (match - this->s);
00123 return -1;
00124 }
00125
00126 const int
00127 N = sizeof(Word),
00128 ByteBits = 8,
00129 WordBits = N * 8;
00130
00131 Word RotateWord(Word w, int b) throw ()
00132
00133
00134 {
00135 b = (b % WordBits);
00136
00137
00138
00139
00140
00141 #if BYTE_ORDER == BIG_ENDIAN
00142 if (b < 0)
00143 {
00144 b = -b;
00145 Word hiMask = (((Word) -1) << b);
00146 Word loMask = (((Word) -1) ^ hiMask);
00147 w = ((w & loMask) << (WordBits - b)) | ((w & hiMask) >> b);
00148 }
00149 #else
00150
00151 if (b > 0)
00152 {
00153 Word hiMask = (((Word) -1) << (WordBits - b));
00154 Word loMask = (((Word) -1) ^ hiMask);
00155 w = ((w & loMask) << b) | ((w & hiMask) >> (WordBits - b));
00156 }
00157 #endif
00158
00159 return w;
00160 }
00161
00162 const int
00163 Up1 = ByteBits,
00164 LgUp1 = 3;
00165
00166 Word Text::Hash() const throw ()
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 {
00191 const PointerInt modNmask = (Word)N - 1UL;
00192 Word temp = 0UL;
00193 const char *p = this->s;
00194 Word m = (Word)strlen(p);
00195 const char *endp = p + m;
00196
00197 #if defined(VALGRIND_SUPPORT)
00198
00199
00200 char *temp_c = ((char *) &temp);
00201 for(unsigned int i = 0; i < m; i++)
00202 {
00203 temp_c[i % sizeof(temp)] ^= this->s[i];
00204 }
00205 return m + temp;
00206 #else
00207
00208 PointerInt jpre = (PointerInt)p & modNmask, jpost;
00209 if ((jpre != 0) && (p != endp))
00210 {
00211
00212
00213
00214 jpost = max(0, N - jpre - m);
00215
00216
00217
00218 temp = *((Word *)(p-jpre));
00219
00220
00221
00222
00223 #if BYTE_ORDER == BIG_ENDIAN
00224 temp <<= (jpre << LgUp1);
00225 temp >>= ((jpost + jpre) << LgUp1);
00226 #else
00227 temp >>= (jpre << LgUp1);
00228 temp <<= ((jpost + jpre) << LgUp1);
00229 #endif
00230
00231
00232
00233 p += (N - jpre - jpost);
00234 }
00235
00236
00237 while (p + N <= endp) {
00238 temp ^= *((Word *)p);
00239 p += N;
00240 }
00241
00242
00243 if (p != endp)
00244 {
00245
00246
00247 Word w = *((Word *)p);
00248
00249
00250
00251
00252 jpost = N - (endp - p);
00253 Word jpostUp1 = (jpost << LgUp1);
00254
00255
00256
00257
00258
00259 #if BYTE_ORDER == BIG_ENDIAN
00260 w >>= jpostUp1;
00261 temp = RotateWord(temp, -jpostUp1);
00262 #else
00263 w <<= jpostUp1;
00264 temp = RotateWord(temp, jpostUp1);
00265 #endif
00266
00267
00268
00269 temp ^= w;
00270 }
00271
00272
00273
00274
00275
00276
00277 #if BYTE_ORDER == BIG_ENDIAN
00278 return m + RotateWord(temp, -(m << LgUp1));
00279 #else
00280 return m + RotateWord(temp, (m << LgUp1));
00281 #endif
00282
00283 #endif // SAFE_HASH
00284 }
00285
00286 Text Text::WordWrap(const Text &prefix, unsigned int columns)
00287 const throw ()
00288 {
00289 Text result = prefix;
00290 unsigned int line_len = result.Length();
00291 const char *read_p = s;
00292
00293
00294 while(*read_p)
00295 {
00296
00297 const char *next_word_start = read_p, *next_word_end;
00298 while(*next_word_start && isspace(*next_word_start))
00299 next_word_start++;
00300 next_word_end = next_word_start;
00301 while(*next_word_end && !isspace(*next_word_end))
00302 next_word_end++;
00303
00304
00305
00306 if((line_len + (next_word_end - read_p)) > columns)
00307 {
00308
00309
00310 unsigned int next_word_len = (next_word_end - next_word_start);
00311 result += (Text("\n") + prefix +
00312 Text(next_word_start, next_word_len));
00313 line_len = prefix.Length() + next_word_len;
00314 }
00315
00316
00317 else
00318 {
00319 unsigned int added_len = (next_word_end - read_p);
00320 result += Text(read_p, added_len);
00321 line_len += added_len;
00322 }
00323
00324
00325 read_p = next_word_end;
00326 }
00327
00328
00329 return result;
00330 }
00331
00332
00333
00334
00335
00336 static void PaddingCopies(unsigned int baseLen,
00337 unsigned int finalLen,
00338 unsigned int padLen,
00339 unsigned int &copies,
00340 unsigned int &partial,
00341 char *&dest)
00342 {
00343 assert(padLen > 0);
00344 unsigned int needed = (finalLen > baseLen) ? (finalLen - baseLen) : 0;
00345 copies = needed/padLen;
00346 partial = needed - (copies*padLen);
00347 unsigned int totalLen = baseLen + (copies*padLen) + partial;
00348 assert(totalLen >= finalLen);
00349 dest = NEW_PTRFREE_ARRAY(char, totalLen+1);
00350 *dest = 0;
00351 }
00352
00353
00354
00355
00356 static void CopyPadding(unsigned int copies, unsigned int partial,
00357 char *dest, const Text &padding)
00358 {
00359 while(copies > 0)
00360 {
00361 strcat(dest, padding.cchars());
00362 copies--;
00363 }
00364 if(partial)
00365 {
00366 strncat(dest, padding.cchars(), partial);
00367 }
00368 }
00369
00370 Text Text::PadLeft(unsigned int toLen, const Text &padding)
00371 const throw()
00372 {
00373
00374 unsigned int copies, partial;
00375 char *dest;
00376 PaddingCopies(this->Length(), toLen, padding.Length(),
00377 copies, partial, dest);
00378
00379
00380 CopyPadding(copies, partial, dest, padding);
00381
00382 strcat(dest, this->s);
00383
00384 Text res;
00385 res.s = dest;
00386 return res;
00387 }
00388
00389 Text Text::PadRight(unsigned int toLen, const Text &padding)
00390 const throw()
00391 {
00392 unsigned int copies, partial;
00393 char *dest;
00394 PaddingCopies(this->Length(), toLen, padding.Length(),
00395 copies, partial, dest);
00396
00397
00398 strcat(dest, this->s);
00399
00400 CopyPadding(copies, partial, dest, padding);
00401
00402 Text res;
00403 res.s = dest;
00404 return res;
00405 }