Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
sqstdrex.cpp
00001 /* see copyright notice in squirrel.h */ 00002 #include <squirrel.h> 00003 #include <string.h> 00004 #include <ctype.h> 00005 #include <setjmp.h> 00006 #include <sqstdstring.h> 00007 00008 #ifdef _UINCODE 00009 #define scisprint iswprint 00010 #else 00011 #define scisprint isprint 00012 #endif 00013 00014 #ifdef _DEBUG 00015 #include <stdio.h> 00016 00017 static const SQChar *g_nnames[] = 00018 { 00019 _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"), 00020 _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"), 00021 _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"), 00022 _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB") 00023 }; 00024 00025 #endif 00026 00027 #define OP_GREEDY (MAX_CHAR+1) // * + ? {n} 00028 #define OP_OR (MAX_CHAR+2) 00029 #define OP_EXPR (MAX_CHAR+3) //parentesis () 00030 #define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:) 00031 #define OP_DOT (MAX_CHAR+5) 00032 #define OP_CLASS (MAX_CHAR+6) 00033 #define OP_CCLASS (MAX_CHAR+7) 00034 #define OP_NCLASS (MAX_CHAR+8) //negates class the [^ 00035 #define OP_RANGE (MAX_CHAR+9) 00036 #define OP_CHAR (MAX_CHAR+10) 00037 #define OP_EOL (MAX_CHAR+11) 00038 #define OP_BOL (MAX_CHAR+12) 00039 #define OP_WB (MAX_CHAR+13) 00040 00041 #define SQREX_SYMBOL_ANY_CHAR ('.') 00042 #define SQREX_SYMBOL_GREEDY_ONE_OR_MORE ('+') 00043 #define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*') 00044 #define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?') 00045 #define SQREX_SYMBOL_BRANCH ('|') 00046 #define SQREX_SYMBOL_END_OF_STRING ('$') 00047 #define SQREX_SYMBOL_BEGINNING_OF_STRING ('^') 00048 #define SQREX_SYMBOL_ESCAPE_CHAR ('\\') 00049 00050 00051 typedef int SQRexNodeType; 00052 00053 typedef struct tagSQRexNode{ 00054 SQRexNodeType type; 00055 SQInteger left; 00056 SQInteger right; 00057 SQInteger next; 00058 }SQRexNode; 00059 00060 struct SQRex{ 00061 const SQChar *_eol; 00062 const SQChar *_bol; 00063 const SQChar *_p; 00064 SQInteger _first; 00065 SQInteger _op; 00066 SQRexNode *_nodes; 00067 SQInteger _nallocated; 00068 SQInteger _nsize; 00069 SQInteger _nsubexpr; 00070 SQRexMatch *_matches; 00071 SQInteger _currsubexp; 00072 void *_jmpbuf; 00073 const SQChar **_error; 00074 }; 00075 00076 static SQInteger sqstd_rex_list(SQRex *exp); 00077 00078 static SQInteger sqstd_rex_newnode(SQRex *exp, SQRexNodeType type) 00079 { 00080 SQRexNode n; 00081 n.type = type; 00082 n.next = n.right = n.left = -1; 00083 if(type == OP_EXPR) 00084 n.right = exp->_nsubexpr++; 00085 if(exp->_nallocated < (exp->_nsize + 1)) { 00086 SQInteger oldsize = exp->_nallocated; 00087 exp->_nallocated *= 2; 00088 exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode)); 00089 } 00090 exp->_nodes[exp->_nsize++] = n; 00091 SQInteger newid = exp->_nsize - 1; 00092 return (SQInteger)newid; 00093 } 00094 00095 static void sqstd_rex_error(SQRex *exp,const SQChar *error) 00096 { 00097 if(exp->_error) *exp->_error = error; 00098 longjmp(*((jmp_buf*)exp->_jmpbuf),-1); 00099 } 00100 00101 static void sqstd_rex_expect(SQRex *exp, SQInteger n){ 00102 if((*exp->_p) != n) 00103 sqstd_rex_error(exp, _SC("expected paren")); 00104 exp->_p++; 00105 } 00106 00107 static SQChar sqstd_rex_escapechar(SQRex *exp) 00108 { 00109 if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){ 00110 exp->_p++; 00111 switch(*exp->_p) { 00112 case 'v': exp->_p++; return '\v'; 00113 case 'n': exp->_p++; return '\n'; 00114 case 't': exp->_p++; return '\t'; 00115 case 'r': exp->_p++; return '\r'; 00116 case 'f': exp->_p++; return '\f'; 00117 default: return (*exp->_p++); 00118 } 00119 } else if(!scisprint(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected")); 00120 return (*exp->_p++); 00121 } 00122 00123 static SQInteger sqstd_rex_charclass(SQRex *exp,SQInteger classid) 00124 { 00125 SQInteger n = sqstd_rex_newnode(exp,OP_CCLASS); 00126 exp->_nodes[n].left = classid; 00127 return n; 00128 } 00129 00130 static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass) 00131 { 00132 SQChar t; 00133 if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) { 00134 exp->_p++; 00135 switch(*exp->_p) { 00136 case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n'); 00137 case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t'); 00138 case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r'); 00139 case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f'); 00140 case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v'); 00141 case 'a': case 'A': case 'w': case 'W': case 's': case 'S': 00142 case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': 00143 case 'p': case 'P': case 'l': case 'u': 00144 { 00145 t = *exp->_p; exp->_p++; 00146 return sqstd_rex_charclass(exp,t); 00147 } 00148 case 'b': 00149 case 'B': 00150 if(!isclass) { 00151 SQInteger node = sqstd_rex_newnode(exp,OP_WB); 00152 exp->_nodes[node].left = *exp->_p; 00153 exp->_p++; 00154 return node; 00155 } //else default 00156 default: 00157 t = *exp->_p; exp->_p++; 00158 return sqstd_rex_newnode(exp,t); 00159 } 00160 } 00161 else if(!scisprint(*exp->_p)) { 00162 00163 sqstd_rex_error(exp,_SC("letter expected")); 00164 } 00165 t = *exp->_p; exp->_p++; 00166 return sqstd_rex_newnode(exp,t); 00167 } 00168 static SQInteger sqstd_rex_class(SQRex *exp) 00169 { 00170 SQInteger ret = -1; 00171 SQInteger first = -1,chain; 00172 if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){ 00173 ret = sqstd_rex_newnode(exp,OP_NCLASS); 00174 exp->_p++; 00175 }else ret = sqstd_rex_newnode(exp,OP_CLASS); 00176 00177 if(*exp->_p == ']') sqstd_rex_error(exp,_SC("empty class")); 00178 chain = ret; 00179 while(*exp->_p != ']' && exp->_p != exp->_eol) { 00180 if(*exp->_p == '-' && first != -1){ 00181 SQInteger r; 00182 if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range")); 00183 r = sqstd_rex_newnode(exp,OP_RANGE); 00184 if(exp->_nodes[first].type>*exp->_p) sqstd_rex_error(exp,_SC("invalid range")); 00185 if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges")); 00186 exp->_nodes[r].left = exp->_nodes[first].type; 00187 SQInteger t = sqstd_rex_escapechar(exp); 00188 exp->_nodes[r].right = t; 00189 exp->_nodes[chain].next = r; 00190 chain = r; 00191 first = -1; 00192 } 00193 else{ 00194 if(first!=-1){ 00195 SQInteger c = first; 00196 exp->_nodes[chain].next = c; 00197 chain = c; 00198 first = sqstd_rex_charnode(exp,SQTrue); 00199 } 00200 else{ 00201 first = sqstd_rex_charnode(exp,SQTrue); 00202 } 00203 } 00204 } 00205 if(first!=-1){ 00206 SQInteger c = first; 00207 exp->_nodes[chain].next = c; 00208 chain = c; 00209 first = -1; 00210 } 00211 /* hack? */ 00212 exp->_nodes[ret].left = exp->_nodes[ret].next; 00213 exp->_nodes[ret].next = -1; 00214 return ret; 00215 } 00216 00217 static SQInteger sqstd_rex_parsenumber(SQRex *exp) 00218 { 00219 SQInteger ret = *exp->_p-'0'; 00220 SQInteger positions = 10; 00221 exp->_p++; 00222 while(isdigit(*exp->_p)) { 00223 ret = ret*10+(*exp->_p++-'0'); 00224 if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant")); 00225 positions *= 10; 00226 }; 00227 return ret; 00228 } 00229 00230 static SQInteger sqstd_rex_element(SQRex *exp) 00231 { 00232 SQInteger ret = -1; 00233 switch(*exp->_p) 00234 { 00235 case '(': { 00236 SQInteger expr; 00237 exp->_p++; 00238 00239 00240 if(*exp->_p =='?') { 00241 exp->_p++; 00242 sqstd_rex_expect(exp,':'); 00243 expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR); 00244 } 00245 else 00246 expr = sqstd_rex_newnode(exp,OP_EXPR); 00247 SQInteger newn = sqstd_rex_list(exp); 00248 exp->_nodes[expr].left = newn; 00249 ret = expr; 00250 sqstd_rex_expect(exp,')'); 00251 } 00252 break; 00253 case '[': 00254 exp->_p++; 00255 ret = sqstd_rex_class(exp); 00256 sqstd_rex_expect(exp,']'); 00257 break; 00258 case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break; 00259 case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break; 00260 default: 00261 ret = sqstd_rex_charnode(exp,SQFalse); 00262 break; 00263 } 00264 00265 00266 SQBool isgreedy = SQFalse; 00267 unsigned short p0 = 0, p1 = 0; 00268 switch(*exp->_p){ 00269 case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break; 00270 case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break; 00271 case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = SQTrue; break; 00272 case '{': 00273 exp->_p++; 00274 if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected")); 00275 p0 = (unsigned short)sqstd_rex_parsenumber(exp); 00276 /*******************************/ 00277 switch(*exp->_p) { 00278 case '}': 00279 p1 = p0; exp->_p++; 00280 break; 00281 case ',': 00282 exp->_p++; 00283 p1 = 0xFFFF; 00284 if(isdigit(*exp->_p)){ 00285 p1 = (unsigned short)sqstd_rex_parsenumber(exp); 00286 } 00287 sqstd_rex_expect(exp,'}'); 00288 break; 00289 default: 00290 sqstd_rex_error(exp,_SC(", or } expected")); 00291 } 00292 /*******************************/ 00293 isgreedy = SQTrue; 00294 break; 00295 00296 } 00297 if(isgreedy) { 00298 SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY); 00299 exp->_nodes[nnode].left = ret; 00300 exp->_nodes[nnode].right = ((p0)<<16)|p1; 00301 ret = nnode; 00302 } 00303 00304 if((*exp->_p != SQREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != SQREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != SQREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) { 00305 SQInteger nnode = sqstd_rex_element(exp); 00306 exp->_nodes[ret].next = nnode; 00307 } 00308 00309 return ret; 00310 } 00311 00312 static SQInteger sqstd_rex_list(SQRex *exp) 00313 { 00314 SQInteger ret=-1,e; 00315 if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) { 00316 exp->_p++; 00317 ret = sqstd_rex_newnode(exp,OP_BOL); 00318 } 00319 e = sqstd_rex_element(exp); 00320 if(ret != -1) { 00321 exp->_nodes[ret].next = e; 00322 } 00323 else ret = e; 00324 00325 if(*exp->_p == SQREX_SYMBOL_BRANCH) { 00326 SQInteger temp,tright; 00327 exp->_p++; 00328 temp = sqstd_rex_newnode(exp,OP_OR); 00329 exp->_nodes[temp].left = ret; 00330 tright = sqstd_rex_list(exp); 00331 exp->_nodes[temp].right = tright; 00332 ret = temp; 00333 } 00334 return ret; 00335 } 00336 00337 static SQBool sqstd_rex_matchcclass(SQInteger cclass,SQChar c) 00338 { 00339 switch(cclass) { 00340 case 'a': return isalpha(c)?SQTrue:SQFalse; 00341 case 'A': return !isalpha(c)?SQTrue:SQFalse; 00342 case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse; 00343 case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse; 00344 case 's': return isspace(c)?SQTrue:SQFalse; 00345 case 'S': return !isspace(c)?SQTrue:SQFalse; 00346 case 'd': return isdigit(c)?SQTrue:SQFalse; 00347 case 'D': return !isdigit(c)?SQTrue:SQFalse; 00348 case 'x': return isxdigit(c)?SQTrue:SQFalse; 00349 case 'X': return !isxdigit(c)?SQTrue:SQFalse; 00350 case 'c': return iscntrl(c)?SQTrue:SQFalse; 00351 case 'C': return !iscntrl(c)?SQTrue:SQFalse; 00352 case 'p': return ispunct(c)?SQTrue:SQFalse; 00353 case 'P': return !ispunct(c)?SQTrue:SQFalse; 00354 case 'l': return islower(c)?SQTrue:SQFalse; 00355 case 'u': return isupper(c)?SQTrue:SQFalse; 00356 } 00357 return SQFalse; /*cannot happen*/ 00358 } 00359 00360 static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQChar c) 00361 { 00362 do { 00363 switch(node->type) { 00364 case OP_RANGE: 00365 if(c >= node->left && c <= node->right) return SQTrue; 00366 break; 00367 case OP_CCLASS: 00368 if(sqstd_rex_matchcclass(node->left,c)) return SQTrue; 00369 break; 00370 default: 00371 if(c == node->type)return SQTrue; 00372 } 00373 } while((node->next != -1) && (node = &exp->_nodes[node->next])); 00374 return SQFalse; 00375 } 00376 00377 static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str,SQRexNode *next) 00378 { 00379 00380 SQRexNodeType type = node->type; 00381 switch(type) { 00382 case OP_GREEDY: { 00383 //SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; 00384 SQRexNode *greedystop = NULL; 00385 SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; 00386 const SQChar *s=str, *good = str; 00387 00388 if(node->next != -1) { 00389 greedystop = &exp->_nodes[node->next]; 00390 } 00391 else { 00392 greedystop = next; 00393 } 00394 00395 while((nmaches == 0xFFFF || nmaches < p1)) { 00396 00397 const SQChar *stop; 00398 if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) 00399 break; 00400 nmaches++; 00401 good=s; 00402 if(greedystop) { 00403 //checks that 0 matches satisfy the expression(if so skips) 00404 //if not would always stop(for instance if is a '?') 00405 if(greedystop->type != OP_GREEDY || 00406 (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) 00407 { 00408 SQRexNode *gnext = NULL; 00409 if(greedystop->next != -1) { 00410 gnext = &exp->_nodes[greedystop->next]; 00411 }else if(next && next->next != -1){ 00412 gnext = &exp->_nodes[next->next]; 00413 } 00414 stop = sqstd_rex_matchnode(exp,greedystop,s,gnext); 00415 if(stop) { 00416 //if satisfied stop it 00417 if(p0 == p1 && p0 == nmaches) break; 00418 else if(nmaches >= p0 && p1 == 0xFFFF) break; 00419 else if(nmaches >= p0 && nmaches <= p1) break; 00420 } 00421 } 00422 } 00423 00424 if(s >= exp->_eol) 00425 break; 00426 } 00427 if(p0 == p1 && p0 == nmaches) return good; 00428 else if(nmaches >= p0 && p1 == 0xFFFF) return good; 00429 else if(nmaches >= p0 && nmaches <= p1) return good; 00430 return NULL; 00431 } 00432 case OP_OR: { 00433 const SQChar *asd = str; 00434 SQRexNode *temp=&exp->_nodes[node->left]; 00435 while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { 00436 if(temp->next != -1) 00437 temp = &exp->_nodes[temp->next]; 00438 else 00439 return asd; 00440 } 00441 asd = str; 00442 temp = &exp->_nodes[node->right]; 00443 while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { 00444 if(temp->next != -1) 00445 temp = &exp->_nodes[temp->next]; 00446 else 00447 return asd; 00448 } 00449 return NULL; 00450 break; 00451 } 00452 case OP_EXPR: 00453 case OP_NOCAPEXPR:{ 00454 SQRexNode *n = &exp->_nodes[node->left]; 00455 const SQChar *cur = str; 00456 SQInteger capture = -1; 00457 if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { 00458 capture = exp->_currsubexp; 00459 exp->_matches[capture].begin = cur; 00460 exp->_currsubexp++; 00461 } 00462 int tempcap = exp->_currsubexp; 00463 do { 00464 SQRexNode *subnext = NULL; 00465 if(n->next != -1) { 00466 subnext = &exp->_nodes[n->next]; 00467 }else { 00468 subnext = next; 00469 } 00470 if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) { 00471 if(capture != -1){ 00472 exp->_matches[capture].begin = 0; 00473 exp->_matches[capture].len = 0; 00474 } 00475 return NULL; 00476 } 00477 } while((n->next != -1) && (n = &exp->_nodes[n->next])); 00478 00479 exp->_currsubexp = tempcap; 00480 if(capture != -1) 00481 exp->_matches[capture].len = cur - exp->_matches[capture].begin; 00482 return cur; 00483 } 00484 case OP_WB: 00485 if((str == exp->_bol && !isspace(*str)) 00486 || (str == exp->_eol && !isspace(*(str-1))) 00487 || (!isspace(*str) && isspace(*(str+1))) 00488 || (isspace(*str) && !isspace(*(str+1))) ) { 00489 return (node->left == 'b')?str:NULL; 00490 } 00491 return (node->left == 'b')?NULL:str; 00492 case OP_BOL: 00493 if(str == exp->_bol) return str; 00494 return NULL; 00495 case OP_EOL: 00496 if(str == exp->_eol) return str; 00497 return NULL; 00498 case OP_DOT:{ 00499 str++; 00500 } 00501 return str; 00502 case OP_NCLASS: 00503 case OP_CLASS: 00504 if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) { 00505 str++; 00506 return str; 00507 } 00508 return NULL; 00509 case OP_CCLASS: 00510 if(sqstd_rex_matchcclass(node->left,*str)) { 00511 str++; 00512 return str; 00513 } 00514 return NULL; 00515 default: /* char */ 00516 if(*str != node->type) return NULL; 00517 str++; 00518 return str; 00519 } 00520 return NULL; 00521 } 00522 00523 /* public api */ 00524 SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error) 00525 { 00526 SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex)); 00527 exp->_eol = exp->_bol = NULL; 00528 exp->_p = pattern; 00529 exp->_nallocated = (SQInteger)scstrlen(pattern) * sizeof(SQChar); 00530 exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode)); 00531 exp->_nsize = 0; 00532 exp->_matches = 0; 00533 exp->_nsubexpr = 0; 00534 exp->_first = sqstd_rex_newnode(exp,OP_EXPR); 00535 exp->_error = error; 00536 exp->_jmpbuf = sq_malloc(sizeof(jmp_buf)); 00537 if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { 00538 SQInteger res = sqstd_rex_list(exp); 00539 exp->_nodes[exp->_first].left = res; 00540 if(*exp->_p!='\0') 00541 sqstd_rex_error(exp,_SC("unexpected character")); 00542 #ifdef _DEBUG 00543 { 00544 SQInteger nsize,i; 00545 SQRexNode *t; 00546 nsize = exp->_nsize; 00547 t = &exp->_nodes[0]; 00548 scprintf(_SC("\n")); 00549 for(i = 0;i < nsize; i++) { 00550 if(exp->_nodes[i].type>MAX_CHAR) 00551 scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); 00552 else 00553 scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type); 00554 scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next); 00555 } 00556 scprintf(_SC("\n")); 00557 } 00558 #endif 00559 exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch)); 00560 memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch)); 00561 } 00562 else{ 00563 sqstd_rex_free(exp); 00564 return NULL; 00565 } 00566 return exp; 00567 } 00568 00569 void sqstd_rex_free(SQRex *exp) 00570 { 00571 if(exp) { 00572 if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode)); 00573 if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf)); 00574 if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch)); 00575 sq_free(exp,sizeof(SQRex)); 00576 } 00577 } 00578 00579 SQBool sqstd_rex_match(SQRex* exp,const SQChar* text) 00580 { 00581 const SQChar* res = NULL; 00582 exp->_bol = text; 00583 exp->_eol = text + scstrlen(text); 00584 exp->_currsubexp = 0; 00585 res = sqstd_rex_matchnode(exp,exp->_nodes,text,NULL); 00586 if(res == NULL || res != exp->_eol) 00587 return SQFalse; 00588 return SQTrue; 00589 } 00590 00591 SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end) 00592 { 00593 const SQChar *cur = NULL; 00594 SQInteger node = exp->_first; 00595 if(text_begin >= text_end) return SQFalse; 00596 exp->_bol = text_begin; 00597 exp->_eol = text_end; 00598 do { 00599 cur = text_begin; 00600 while(node != -1) { 00601 exp->_currsubexp = 0; 00602 cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,NULL); 00603 if(!cur) 00604 break; 00605 node = exp->_nodes[node].next; 00606 } 00607 text_begin++; 00608 } while(cur == NULL && text_begin != text_end); 00609 00610 if(cur == NULL) 00611 return SQFalse; 00612 00613 --text_begin; 00614 00615 if(out_begin) *out_begin = text_begin; 00616 if(out_end) *out_end = cur; 00617 return SQTrue; 00618 } 00619 00620 SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end) 00621 { 00622 return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end); 00623 } 00624 00625 SQInteger sqstd_rex_getsubexpcount(SQRex* exp) 00626 { 00627 return exp->_nsubexpr; 00628 } 00629 00630 SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp) 00631 { 00632 if( n<0 || n >= exp->_nsubexpr) return SQFalse; 00633 *subexp = exp->_matches[n]; 00634 return SQTrue; 00635 } 00636
Generated on Tue Jul 12 2022 21:35:49 by
1.7.2