Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

htstring.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      htstring.cc
00004  *
00005  *      Copyright (C) 1999-2002 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 //              if (*s<32) *result=' '; else *result=*s;
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 /* common string parsing functions */
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 static bool bnstr2bin(char *str, char *p, int base, dword *v)
00358 {
00359         *v=0;
00360         do {
00361                 int c=hexdigit(*str);
00362                 if ((c==-1) || (c>=base)) return false;
00363                 (*v)*=base;
00364                 *v+=c;
00365                 str++;
00366         } while (str<p);
00367         return true;
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; /* zero length */
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 /* hex/string functions */
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  *      CLASS ht_data_string
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  *      CLASS ht_string_list
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  *      CLASS ht_sorted_string_list
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  *      compare_keys_string
00619  */
00620 
00621 int compare_keys_string(Object *key_a, Object *key_b)
00622 {
00623         // FIXME:
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  *      icompare_keys_string
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  *      INIT
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  *      DONE
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 

Generated on Fri May 7 21:15:37 2004 by doxygen 1.3.5