00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "global.h"
00022 #include "htatom.h"
00023 #include "htdebug.h"
00024 #include "htstring.h"
00025 #include "snprintf.h"
00026 #include "stream.h"
00027 #include "tools.h"
00028
00029 #include <ctype.h>
00030 #include <stdarg.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033
00034 #define ATOM_HT_DATA_STRING MAGICD("STR\x00")
00035 #define ATOM_COMPARE_KEYS_STRING MAGICD("STR\x10")
00036 #define ATOM_ICOMPARE_KEYS_STRING MAGICD("STR\x11")
00037
00038 char hexchars[17]="0123456789abcdef";
00039
00040 char *ht_strdup(const char *str)
00041 {
00042 if (str) {
00043 int len = strlen(str)+1;
00044 char *s = (char*)smalloc(len);
00045 memmove(s, str, len);
00046 return s;
00047 } else {
00048 return NULL;
00049 }
00050 }
00051
00056 char *ht_strndup(const char *str, int maxlen)
00057 {
00058 maxlen ++;
00059 if (str) {
00060 int len = strlen(str)+1;
00061 len = MIN(len, maxlen);
00062 char *s = (char*)smalloc(len);
00063 memmove(s, str, len);
00064 return s;
00065 } else {
00066 return NULL;
00067 }
00068 }
00069
00077 int ht_strncpy(char *s1, const char *s2, int maxlen)
00078 {
00079 if (maxlen <= 0) return 0;
00080 char *os1 = s1;
00081 while (maxlen && *s2) {
00082 *s1 = *s2;
00083 maxlen--;
00084 s1++;
00085 }
00086 s1[-1] = 0;
00087 return s1-os1-1;
00088 }
00089
00090
00091 int ht_strncmp(const char *s1, const char *s2, size_t max)
00092 {
00093 if (!s1) return s2 ? -1 : 0;
00094 if (!s2) return s1 ? 1 : 0;
00095 while (max--) {
00096 if (!*s1) return *s2 ? -1 : 0;
00097 if (!*s2) return *s1 ? 1 : 0;
00098 if (*s1>*s2) {
00099 return 1;
00100 } else if (*s1<*s2) {
00101 return -1;
00102 }
00103 s1++;s2++;
00104 }
00105 return 0;
00106 }
00107
00108 int ht_strnicmp(const char *s1, const char *s2, size_t max)
00109 {
00110 if (!s1) return s2 ? -1 : 0;
00111 if (!s2) return s1 ? 1 : 0;
00112 while (max--) {
00113 if (!*s1) return *s2 ? -1 : 0;
00114 if (!*s2) return *s1 ? 1 : 0;
00115 char c1=tolower(*s1), c2=tolower(*s2);
00116 if (c1>c2) {
00117 return 1;
00118 } else if (c1<c2) {
00119 return -1;
00120 }
00121 s1++;s2++;
00122 }
00123 return 0;
00124 }
00125
00126 int ht_stricmp(const char *s1, const char *s2)
00127 {
00128 if (!s1) return s2 ? -1 : 0;
00129 if (!s2) return s1 ? 1 : 0;
00130 while (1) {
00131 if (!*s1) return *s2 ? -1 : 0;
00132 if (!*s2) return *s1 ? 1 : 0;
00133 char c1=tolower(*s1), c2=tolower(*s2);
00134 if (c1>c2) {
00135 return 1;
00136 } else if (c1<c2) {
00137 return -1;
00138 }
00139 s1++;s2++;
00140 }
00141 return 0;
00142 }
00143
00144 int strccomm(const char *s1, const char *s2)
00145 {
00146 if (!s1 || !s2) return 0;
00147 int r=0;
00148 while (*s1 && *s2 && (*s1==*s2)) { s1++; s2++; r++; }
00149 return r;
00150 }
00151
00152 int strcicomm(const char *s1, const char *s2)
00153 {
00154 if (!s1 || !s2) return 0;
00155 int r=0;
00156 while (*s1 && *s2 && (tolower(*s1)==tolower(*s2))) { s1++; s2++; r++; }
00157 return r;
00158 }
00159
00160 int escape_special_str(char *result, int resultmaxlen, const char *s, const char *specialchars, bool bit7)
00161 {
00162 return escape_special(result, resultmaxlen, s, strlen(s), specialchars, bit7);
00163 }
00164
00165 int escape_special(char *result, int resultmaxlen, const void *S, int len, const char *specialchars, bool bit7)
00166 {
00167 byte *s = (byte*)S;
00168 if (!s) return 0;
00169 char *old = result;
00170 if (!specialchars) specialchars="";
00171 while (len--) {
00172 if (*s && strchr(specialchars, *s)) {
00173 *result++='\\';
00174 if (--resultmaxlen<2) break;
00175 *result++=*s;
00176 if (--resultmaxlen<2) break;
00177 } else if (*s<32 || (bit7 && (*s>0x7f)) || *s=='\\') {
00178 *result++='\\';
00179 if (--resultmaxlen<2) break;
00180 switch (*s) {
00181 case '\0':
00182 *result++='0';
00183 break;
00184 case '\a':
00185 *result++='a';
00186 break;
00187 case '\b':
00188 *result++='b';
00189 break;
00190 case '\e':
00191 *result++='e';
00192 break;
00193 case '\f':
00194 *result++='f';
00195 break;
00196 case '\n':
00197 *result++='n';
00198 break;
00199 case '\r':
00200 *result++='r';
00201 break;
00202 case '\t':
00203 *result++='t';
00204 break;
00205 case '\v':
00206 *result++='v';
00207 break;
00208 case '\\':
00209 *result++='\\';
00210 break;
00211 case '\"':
00212 *result++='"';
00213 break;
00214 default:
00215 *result++='x';
00216 if (--resultmaxlen<2) break;
00217 *result++=hexchars[((*s & 0xf0) >> 4)];
00218 if (--resultmaxlen<2) break;
00219 *result++=hexchars[(*s & 0x0f)];
00220 }
00221 if (--resultmaxlen<2) break;
00222 } else {
00223 *result++ = *s;
00224 if (--resultmaxlen<2) break;
00225 }
00226 s++;
00227 }
00228 *result = 0;
00229 return result-old;
00230 }
00231
00232 int unescape_special_str(char *result, int resultmaxlen, const char *s)
00233 {
00234 int l=unescape_special(result, resultmaxlen-1, s);
00235 result[l]=0;
00236 return l;
00237 }
00238
00239 int unescape_special(void *Result, int resultmaxlen, const char *s)
00240 {
00241 char *result = (char*)Result;
00242 char *old = result;
00243 while (s && *s) {
00244 if (*s == '\\') {
00245 s++;
00246 switch (*s) {
00247 case '0':
00248 *result++='\0';
00249 break;
00250 case 'a':
00251 *result++='\a';
00252 break;
00253 case 'b':
00254 *result++='\b';
00255 break;
00256 case 'e':
00257 *result++='\e';
00258 break;
00259 case 'f':
00260 *result++='\f';
00261 break;
00262 case 'n':
00263 *result++='\n';
00264 break;
00265 case 'r':
00266 *result++='\r';
00267 break;
00268 case 't':
00269 *result++='\t';
00270 break;
00271 case 'v':
00272 *result++='\v';
00273 break;
00274 case '\\':
00275 *result++='\\';
00276 break;
00277 case '\"':
00278 *result++='"';
00279 break;
00280 case 'x':
00281 s++;
00282 byte v=hexdigit(*s)*16;
00283 s++;
00284 v+=hexdigit(*s);
00285 *result++=(char)v;
00286 }
00287 if (!--resultmaxlen) break;
00288 } else {
00289 *result++ = *s;
00290 if (!--resultmaxlen) break;
00291 }
00292 s++;
00293 }
00294 return result-old;
00295 }
00296
00297 int bin2str(char *result, const void *S, int len)
00298 {
00299 byte *s = (byte*)S;
00300 while (len--) {
00301
00302 if (*s==0) *result=' '; else *result=*s;
00303 result++;
00304 s++;
00305 }
00306 *result=0;
00307 return len;
00308 }
00309
00310 void wide_char_to_multi_byte(char *result, const byte *Unicode, int maxlen)
00311 {
00312 if (!maxlen) return;
00313 struct doof {
00314 char c1;
00315 char c2;
00316 };
00317 doof *unicode = (doof*)Unicode;
00318 for (int i=0; i<maxlen-1; i++) {
00319 if (unicode->c2) {
00320 *result++ = '”';
00321 } else {
00322 if (!unicode->c1) break;
00323 *result++ = unicode->c1;
00324 }
00325 unicode++;
00326 }
00327 *result=0;
00328 }
00329
00330
00331
00332 void whitespaces(char **str)
00333 {
00334 while ((unsigned char)**str<=32) {
00335 if (!**str) return;
00336 (*str)++;
00337 }
00338 }
00339
00340 void non_whitespaces(char **str)
00341 {
00342 while ((unsigned char)**str>32) {
00343 (*str)++;
00344 }
00345 }
00346
00347 bool waitforchar(char **str, char b)
00348 {
00349 while (**str!=b) {
00350 if (!**str) return false;
00351 (*str)++;
00352 }
00353 return true;
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 static bool bnstr2bin(char *str, char *p, int base, qword *q)
00372 {
00373 *q = to_qword(0);
00374 qword qbase = to_qword(base);
00375 do {
00376 int c = hexdigit(*str);
00377 if ((c == -1) || (c >= base)) return false;
00378 (*q) *= qbase;
00379 *q += to_qword(c);
00380 str++;
00381 } while (str < p);
00382 return true;
00383 }
00384
00385 bool bnstr(char **str, qword *q, int defaultbase)
00386 {
00387 int base=defaultbase;
00388 int t=0;
00389 char *p=*str;
00390 while (!strchr("+-*/%()[] \t#.,:;", *p) && (*p)) p++;
00391 if (p==*str) return false;
00392 if (strncmp("0x", *str, 2)==0) {
00393 (*str)+=2;
00394 base=16;
00395 } else {
00396 switch (*(p-1)) {
00397 case 'b':
00398 if (base <= 'b'-'a'+10) {
00399 base = 2;
00400 p--;
00401 t++;
00402 }
00403 break;
00404 case 'o':
00405 if (base <= 'o'-'a'+10) {
00406 base = 8;
00407 p--;
00408 t++;
00409 }
00410 break;
00411 case 'd':
00412 if (base <= 'd'-'a'+10) {
00413 base = 10;
00414 p--;
00415 t++;
00416 }
00417 break;
00418 case 'h':
00419 if (base <= 'h'-'a'+10) {
00420 base = 16;
00421 p--;
00422 t++;
00423 }
00424 break;
00425 default:
00426 if (**str=='0') base=8;
00427 }
00428 }
00429 if (bnstr2bin(*str, p, base, q)) {
00430 *str=p+t;
00431 return true;
00432 }
00433 return false;
00434 }
00435
00436 bool bnstr(char **str, dword *v, int defaultbase)
00437 {
00438 qword q;
00439 bool res = bnstr(str, &q, defaultbase);
00440 *v = QWORD_GET_LO(q);
00441 return res;
00442 }
00443
00444
00445
00446 int hexdigit(char a)
00447 {
00448 if ((a>='0') && (a<='9')) {
00449 return a-'0';
00450 } else if ((a>='a') && (a<='f')) {
00451 return a-'a'+10;
00452 } else if ((a>='A') && (a<='F')) {
00453 return a-'A'+10;
00454 }
00455 return -1;
00456 }
00457
00458 bool hexb_ex(uint8 &result, const char *s)
00459 {
00460 int v, w;
00461 v = hexdigit(s[0]);
00462 w = hexdigit(s[1]);
00463 if ((v < 0) || (w < 0)) return false;
00464 result = (v<<4) | w;
00465 return true;
00466 }
00467
00468 bool hexw_ex(uint16 &result, const char *s)
00469 {
00470 uint8 v, w;
00471 if (!hexb_ex(v, s) || !hexb_ex(w, s+2)) return false;
00472 result = (v<<8) | w;
00473 return true;
00474 }
00475
00476 bool hexd_ex(uint32 &result, const char *s)
00477 {
00478 uint16 v, w;
00479 if (!hexw_ex(v, s) || !hexw_ex(w, s+4)) return false;
00480 result = (v<<16) | w;
00481 return true;
00482 }
00483
00484 char *mkhexb(char *buf, byte d)
00485 {
00486 *buf++=hexchars[(d>>4)&0xf];
00487 *buf++=hexchars[d&0xf];
00488 return buf;
00489 }
00490
00491 char *mkhexw(char *buf, word d)
00492 {
00493 *buf++=hexchars[(d>>12)&0xf];
00494 *buf++=hexchars[(d>>8)&0xf];
00495 *buf++=hexchars[(d>>4)&0xf];
00496 *buf++=hexchars[d&0xf];
00497 return buf;
00498 }
00499
00500 char *mkhexd(char *buf, dword d)
00501 {
00502 *buf++=hexchars[(d>>28)&0xf];
00503 *buf++=hexchars[(d>>24)&0xf];
00504 *buf++=hexchars[(d>>20)&0xf];
00505 *buf++=hexchars[(d>>16)&0xf];
00506 *buf++=hexchars[(d>>12)&0xf];
00507 *buf++=hexchars[(d>>8)&0xf];
00508 *buf++=hexchars[(d>>4)&0xf];
00509 *buf++=hexchars[d&0xf];
00510 return buf;
00511 }
00512
00513 char *mkhexq(char *buf, qword q)
00514 {
00515 *buf++=hexchars[(q.hi>>28)&0xf];
00516 *buf++=hexchars[(q.hi>>24)&0xf];
00517 *buf++=hexchars[(q.hi>>20)&0xf];
00518 *buf++=hexchars[(q.hi>>16)&0xf];
00519 *buf++=hexchars[(q.hi>>12)&0xf];
00520 *buf++=hexchars[(q.hi>>8)&0xf];
00521 *buf++=hexchars[(q.hi>>4)&0xf];
00522 *buf++=hexchars[q.hi&0xf];
00523 *buf++=hexchars[(q.lo>>28)&0xf];
00524 *buf++=hexchars[(q.lo>>24)&0xf];
00525 *buf++=hexchars[(q.lo>>20)&0xf];
00526 *buf++=hexchars[(q.lo>>16)&0xf];
00527 *buf++=hexchars[(q.lo>>12)&0xf];
00528 *buf++=hexchars[(q.lo>>8)&0xf];
00529 *buf++=hexchars[(q.lo>>4)&0xf];
00530 *buf++=hexchars[q.lo&0xf];
00531 return buf;
00532 }
00533
00534
00535
00536
00537
00538 ht_data_string::ht_data_string(const char *s)
00539 {
00540 value = ht_strdup(s);
00541 }
00542
00543 ht_data_string::~ht_data_string()
00544 {
00545 if (value) free(value);
00546 }
00547
00548 int ht_data_string::load(ht_object_stream *f)
00549 {
00550 value = f->getString(NULL);
00551 return f->get_error();
00552 }
00553
00554 void ht_data_string::store(ht_object_stream *f)
00555 {
00556 f->putString(value, NULL);
00557 }
00558
00559 int ht_data_string::toString(char *s, int maxlen)
00560 {
00561 return ht_snprintf(s, maxlen, "%s", value);
00562 }
00563
00564 OBJECT_ID ht_data_string::object_id() const
00565 {
00566 return ATOM_HT_DATA_STRING;
00567 }
00568
00569
00570
00571
00572
00573 void ht_string_list::init()
00574 {
00575 ht_clist::init(compare_keys_string);
00576 }
00577
00578 char *ht_string_list::get_string(UINT i)
00579 {
00580 ht_data_string *s=(ht_data_string*)get(i);
00581 if (s) return s->value;
00582 return 0;
00583 }
00584
00585 void ht_string_list::insert_string(char *s)
00586 {
00587 insert(new ht_data_string(s));
00588 }
00589
00590
00591
00592
00593
00594 void ht_sorted_string_list::init(int (*compare_keys_proc)(Object *key_a, Object *key_b))
00595 {
00596 ht_sorted_list::init(compare_keys_proc);
00597 }
00598
00599 char *ht_sorted_string_list::get_string(char *s)
00600 {
00601 Object *d = new ht_data_string(s);
00602 UINT i=find(d);
00603 char *ret=NULL;
00604 if (i!=LIST_UNDEFINED) {
00605 Object *r=get(i);
00606 if (r) ret=((ht_data_string *)r)->value;
00607 }
00608 delete d;
00609 return ret;
00610 }
00611
00612 void ht_sorted_string_list::insert_string(char *s)
00613 {
00614 insert(new ht_data_string(s));
00615 }
00616
00617
00618
00619
00620
00621 int compare_keys_string(Object *key_a, Object *key_b)
00622 {
00623
00624 if (((ht_data_string*)key_a)->value && ((ht_data_string*)key_b)->value) {
00625 return strcmp(((ht_data_string*)key_a)->value, ((ht_data_string*)key_b)->value);
00626 } else return 0;
00627 }
00628
00629
00630
00631
00632
00633 int icompare_keys_string(Object *key_a, Object *key_b)
00634 {
00635 return ht_stricmp(((ht_data_string*)key_a)->value, ((ht_data_string*)key_b)->value);
00636 }
00637
00638 BUILDER(ATOM_HT_DATA_STRING, ht_data_string);
00639
00640
00641
00642
00643
00644 bool init_string()
00645 {
00646 REGISTER(ATOM_HT_DATA_STRING, ht_data_string);
00647 register_atom(ATOM_COMPARE_KEYS_STRING, (void*)compare_keys_string);
00648 register_atom(ATOM_ICOMPARE_KEYS_STRING, (void*)icompare_keys_string);
00649 return true;
00650 }
00651
00652
00653
00654
00655
00656 void done_string()
00657 {
00658 UNREGISTER(ATOM_HT_DATA_STRING, ht_data_string);
00659 unregister_atom(ATOM_COMPARE_KEYS_STRING);
00660 unregister_atom(ATOM_ICOMPARE_KEYS_STRING);
00661 }
00662