00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "tlstring.h"
00019 #include <lib/serror.h>
00020 #include <stdio.h>
00021
00022 TLString TLString::ParseString(const char *instr,ssize_t inlen,SError &error)
00023 {
00024 if(!instr) return TLString();
00025 if(inlen<0)
00026 { inlen=strlen(instr); }
00027
00028
00029
00030 Assert(instr[inlen]=='\0');
00031
00032
00033 error.clear();
00034
00035
00036 TLString dest_str;
00037
00038
00039
00040
00041 dest_str.d=new SData(inlen+1);
00042 SData *db=dest_str.d;
00043
00044
00045
00046
00049
00050
00051 const char *s=instr,*send=s+inlen;
00052 char *d=db->str;
00053 int8 cnt=0;
00054 bool quotemode=false;
00055 if (*s=='"') {
00056 quotemode=true;
00057 s++;
00058 }
00059 while(s<send)
00060 {
00061 if(*s=='\\')
00062 {
00063 s++;
00064 switch(*s++) {
00065 case 'X':
00066 cnt+=2;
00067 case 'x':
00068 { cnt+=2;
00069 int num=0;
00070 bool valid=false;
00071
00072 do {
00073 if ((*s<='9')&&(*s>='0')) {
00074 num=(num<<4)|(*s-'0');
00075 valid=true;
00076 } else
00077 if ((*s<='F')&&(*s>='A')) {
00078 num=(num<<4)|(*s-'A'+0xa);
00079 valid=true;
00080 } else
00081 if ((*s<='f')&&(*s>='a')) {
00082 num=(num<<4)|(*s-'a'+0xa);
00083 valid=true;
00084 } else {
00085 cnt=0;
00086 if (!valid) {
00087 error=SError("invalid \\x formatting",1);
00088 } else
00089 *d++=num;
00090 if (s>=send) {
00091 goto end_of_string;
00092 }
00093 break;
00094 }
00095 if (cnt&1)
00096 *d++=num;
00097 s++;
00098 } while (--cnt);
00099 } break;
00100
00101 case '0':
00102 { cnt+=3;
00103 interpret_only_two_chars:
00104 int num=0;
00105 do {
00106 if ((*s<='7')&&(*s>='0')) {
00107 num<<=3;
00108 num|=(*s++)-'0';
00109 } else
00110 cnt=1;
00111 } while (--cnt);
00112
00113
00114
00115 if (num>>8) {
00116 cnt=2;
00117 s-=3;
00118 goto interpret_only_two_chars;
00119 }
00120 *d++=num&0xff;
00121 } break;
00122 case 't': *d++='\t'; break;
00123 case 'n': *d++='\n'; break;
00124 case 'r': *d++='\r'; break;
00125 case 'f': *d++='\f'; break;
00126 case 'v': *d++='\v'; break;
00127 case 'a': *d++='\a'; break;
00128 case 'b': *d++='\b'; break;
00129 case '^':
00130 if ((*s<='Z')&&(*s>='A'))
00131 *d++=*s-'A'+1;
00132 else
00133 error=SError("warning: unknown ctrl char",1);
00134 s++;
00135 break;
00136 case '"':
00137 case '\'':
00138 case '\\':
00139 *d++=*(s-1);
00140 break;
00141 default:
00142 error=SError("warning: unknown escape seq",1);
00143 break;
00144 }
00145 }
00146 else
00147 if ((quotemode)&&(*s=='"')) {
00148 bool fault=false;
00149 do {
00150 s++;
00151 switch(*s) {
00152 case ' ':
00153 case '\r':
00154 case '\n':
00155 case '\t':
00156 case '\v':
00157 case '\f':
00158 case '\0': break;
00159 case '"':
00160 ++s;
00161 goto quotation_starts_again;
00162 case '\\': if(s[1]=='\n') break;
00163 default:
00164 fault=true;
00165 break;
00166 }
00167 } while (s<send);
00168 quotation_starts_again:;
00169 if (fault) {
00170 error=SError("non-whitespace between string fragments",1);
00171 }
00172
00173
00174 } else {
00175 *d++=*s++;
00176 }
00177 }
00178 end_of_string:
00179
00180
00181 *d='\0';
00182 db->len=d-db->str;
00183
00184
00185
00186
00187 Assert(db->len<db->asize);
00188 Assert(db->str[db->len]=='\0');
00189
00190
00191
00192 db->DownSizeIfNeeded(db->len+1);
00193
00194 return(dest_str);
00195 }
00196
00197
00198 #if 0
00199
00200 #include <unistd.h>
00201 #include <stdio.h>
00202
00203
00204
00205
00206
00207 static void DoParseString(const char *instr)
00208 {
00209 SError error;
00210 TLString str=TLString::ParseString(instr,-1,error);
00211
00212 fprintf(stderr,"Parsed string has length %u.\n",str.length());
00213
00214
00215
00216
00217 write(2,"str=>",5);
00218 write(2,str.str(),str.length());
00219 write(2,"<\n",2);
00220 for (uint a=0;a<str.length();a++)
00221 printf("%3x",(unsigned char)str.str()[a]);
00222 printf("\n");
00223 if(error)
00224 { fprintf(stderr,"Error occured: %s\n",error.msg().str()); }
00225 }
00226
00227
00228 int main(int argc,char **arg)
00229 {
00230 char *s="\\X5241\\x59.\\X4C41\\X554eCH();\\^M\\^J\\tand_\\0_such";
00231 char*s2="\"this is the line wrapping-(\" \t \t\r\t\n \t\")-test with \\x52\\X4159\"";
00232 s=s2;
00233 if(argc==1)
00234 {
00235 printf("will parse string %s\n",s);
00236 DoParseString(s);
00237 }
00238 bool interactive=0;
00239 for(int i=1; i<argc; i++)
00240 {
00241 DoParseString(arg[i]);
00242 if(arg[i][0]=='-' && !arg[i][1]) interactive=1;
00243 }
00244 if(interactive)
00245 {
00246 const size_t buflen=256;
00247 char buf[buflen];
00248 while(!feof(stdin) && !ferror(stdin))
00249 {
00250 if(!fgets(buf,256,stdin)) continue;
00251 size_t len=strlen(buf);
00252 if(len && buf[len-1]=='\n') buf[--len]='\0';
00253 DoParseString(buf);
00254 }
00255 }
00256
00257 return(0);
00258 }
00259
00260 #endif