6f1df58789d74c0ab7bd1b0fffce39e2db52e8cb
[platform/upstream/syncevolution.git] / src / synthesis / src / sysync_SDK / Sources / stringutil.cpp
1 /*
2  *  File:         stringutil.cpp
3  *
4  *  Authors:      Lukas Zeller (luz@synthesis.ch)
5  *                Beat Forster (bfo@synthesis.ch)
6  *
7  *  C++ string utils
8  *
9  *  Copyright (c) 2001-2009 by Synthesis AG (www.synthesis.ch)
10  *
11  */
12
13 #include "target_options.h"
14
15
16 #if defined __MACH__ && !defined __GNUC__ /* used for va_list support */
17   #include <mw_stdarg.h>
18 #else
19   #include <stdarg.h>
20 #endif
21
22 #ifdef __GNUC__
23   #include <stdio.h>
24 #else
25   #ifndef _MSC_VER
26     #include <ctype>
27   #endif
28 #endif
29
30 #include "stringutil.h"
31
32 #ifdef __cplusplus
33   namespace sysync {
34 #endif
35
36
37 // case insensitive strcmp, NULL allowed as empty string input
38 sInt16 strucmp( cAppCharP s1, cAppCharP s2, size_t len1, size_t len2 )
39 {
40   // allow NULL as empty strings
41   if (!s1) s1 = "";
42   if (!s2) s2 = "";
43   // s1>s2 : 1, s1==s2 : 0, s1<s2 : -1
44   size_t i;
45   // calc number of chars we must compare
46   size_t len = len1==0 ? len2 : (len2==0 ? len1 : (len1>len2 ? len2 : len1));
47   for (i=0; (!len || i<len) && *s1 && *s2; i++) {
48     // while both strings have chars and not len reached
49     if (toupper(*s1)!=toupper(*s2))
50       return toupper(*s1)>toupper(*s2) ? 1 : -1; // different
51     // next
52     s1++;
53     s2++;
54   }
55   // equal up to end of shorter string or reached len
56   // - if both reached end or len -> equal
57   if ( ((len1 ? i==len1 : false) || *s1==0) && ((len2 ? i==len2 : false) || *s2==0) ) return 0;
58   // - not equal, longer string is larger
59   //   (if not reached end of s1 or stopped before len1, s1 is longer
60   //    but note than len1 can be longer than actual length of s1, so we
61   //    must check for *s1 to make sure we have really not reached end of s1)
62   return (len1 ? i<len1 && *s1 : *s1) ? 1 : -1;
63 } // strucmp
64
65
66 // returns number of C-string-escaped chars successfully converted to string
67 sInt16 CStrToStrAppend( cAppCharP aStr, string &aString, bool aStopAtQuoteOrCtrl, char ignore )
68 {
69   unsigned char c;
70   const char *p=aStr;
71   while ((c=*p++)) {
72     // check for escape
73     if (c=='\\') {
74       // escape, check next
75       c=*p++;
76       if (!c) break; // unfinished escape sequence is ignored
77       switch (c) {
78         case 't' : c=0x09; break; // TAB
79         case 'n' : c=0x0A; break; // line feed
80         case 'r' : c=0x0D; break; // carriage return
81         case '\r':
82         case '\n':
83           // continued line, swallow line end
84           c=0;
85           break;
86         case 'x' :
87           // hex char
88           c=0; uInt16 n=0;
89           while (isxdigit(*p) && n<2) {
90             c=(c<<4) | (*p>'9' ? toupper(*p)-'A'+0x0A : *p-'0');
91             p++; n++;
92           }
93           break;
94       }
95       // c is the char to add
96     }
97     else if (aStopAtQuoteOrCtrl && (c=='"' || c<0x20)) {
98       // terminating char is NOT consumed
99       p--;
100       break; // stop here
101     }
102     // otherwise, ignore any control characters
103     else if (c<0x20 && c!=ignore)
104       continue;
105     // add it to the result
106     if (c) aString+=c;
107   }
108   // return number of converted chars
109   return p-aStr;
110 } // CStrToStrAppend
111
112
113 // returns number of string-escaped chars successfully converted to C-string
114 sInt16 StrToCStrAppend( cAppCharP aStr, string &aString, bool aAllow8Bit, char ignore )
115 {
116   unsigned char c;
117   const char *p=aStr;
118   while ((c=*p++)) {
119     // check for specials
120     if      (c==ignore) aString+= c;
121     else if (c==0x09)   aString+="\\t";
122     else if (c==0x0A)   aString+="\\n";
123     else if (c==0x0D)   aString+="\\r";
124     else if (c==0x22)   aString+="\\\"";
125     else if (c=='\\')   aString+="\\\\"; // escape the backslash as well
126     else if (c<0x20 || c==0x7F || (!aAllow8Bit && c>=0x80)) {
127       StringObjAppendPrintf(aString,"\\x%02hX",(uInt16)c);
128     }
129     else {
130       // as is
131       aString+=c;
132     }
133   }
134   // return number of converted chars
135   return p-aStr;
136 } // StrToCStrAppend
137
138
139
140 // old-style C-formatted output into string object
141 static void vStringObjPrintf( string &aStringObj, cAppCharP aFormat, bool aAppend, va_list aArgs )
142 {
143   #ifndef NO_VSNPRINTF
144   const size_t bufsiz=128;
145   #else
146   const size_t bufsiz=2048;
147   #endif
148   int actualsize;
149   char buf[bufsiz];
150
151   buf[0]='\0';
152   char *bufP = NULL;
153   if (!aAppend) aStringObj.erase();
154   actualsize = vsnprintf(buf, bufsiz, aFormat, aArgs);
155
156   #ifndef NO_VSNPRINTF
157   if (actualsize>=(int)bufsiz) {
158     // default buffer was too small, create bigger dynamic buffer
159     bufP = new char[actualsize+1];
160     actualsize = vsnprintf(bufP, actualsize+1, aFormat, aArgs);
161     if (actualsize>0) {
162       aStringObj += bufP;
163     }
164     delete bufP;
165   }
166   else
167   #endif
168
169   {
170     // small default buffer was big enough, add it
171     if (actualsize<0) return; // abort, error
172     aStringObj += buf;
173   }
174 } // vStringObjPrintf
175
176
177 // old-style C-formatted output appending into string object
178 void StringObjAppendPrintf( string &aStringObj, cAppCharP aFormat, ... )
179 {
180   va_list args;
181
182   va_start(args, aFormat);
183   // now make the string
184   vStringObjPrintf(aStringObj,aFormat,true,args);
185   va_end(args);
186 } // StringObjAppendPrintf
187
188
189 // returns number of successfully converted chars
190 sInt16 HexStrToULong( cAppCharP aStr, uInt32 &aLong, sInt16 aMaxDigits )
191 {
192   // our own implementation
193   char c;
194   sInt16 n=0;
195   aLong=0;
196
197   while (aStr && (c=*aStr++) && (n<aMaxDigits)) {
198     if (!isxdigit(c)) break;
199     aLong*= 16;
200     aLong+=(toupper(c)-0x30);
201     if    (!isdigit(c)) aLong-=7;
202     n++;
203   } // while
204
205   return n;
206 } // HexStrToUShort
207
208
209 // returns number of successfully converted chars
210 sInt16 HexStrToULongLong( cAppCharP aStr, uInt64 &aLongLong, sInt16 aMaxDigits )
211 {
212   // our own implementation
213   char c;
214   sInt16 n=0;
215   aLongLong=0;
216
217   while (aStr && (c=*aStr++) && (n<aMaxDigits)) {
218     if (!isxdigit(c)) break;
219     aLongLong*= 16;
220     aLongLong+=(toupper(c)-0x30);
221     if    (!isdigit(c)) aLongLong-=7;
222     n++;
223   } // while
224
225   return n;
226 } // HexStrToULongLong
227
228
229 sInt16 HexStrToUIntPtr( cAppCharP aStr, uIntPtr &aIntPtr, sInt16 aMaxDigits )
230 {
231   #if __WORDSIZE == 64
232     return HexStrToULongLong( aStr, aIntPtr, aMaxDigits );
233   #else
234     uInt32                            v= (uInt32)aIntPtr;
235     sInt16 rslt= HexStrToULong( aStr, v, aMaxDigits );
236     aIntPtr=                 (uIntPtr)v;
237     
238     return rslt;
239   #endif
240 } // HexStrToUIntPtr
241
242
243 #ifdef __cplusplus
244   } // namespace
245 #endif
246
247 /* eof */
248