Преглед изворни кода

Added "%q" from Lua 5.2.1 to format.
Added two new functions "xcapture" and "getxcapture".
Added similar functionality from Lua string.gmatch to squirrel regex, because squirrel do not allow return multiple parameters this implementation takes a function to process the results.

Ex:

some_regex.gmatch(somestring, function(m1, m2){ print(m1, m2);});

mingodad пре 13 година
родитељ
комит
020c5a401f
1 измењених фајлова са 135 додато и 9 уклоњено
  1. 135 9
      sqstdlib/sqstdstring.cpp

+ 135 - 9
sqstdlib/sqstdstring.cpp

@@ -44,7 +44,7 @@ static SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src,
 		width = 0;
 	if (src[n] == '.') {
 	    n++;
-    	
+
 		wc = 0;
 		while (scisdigit(src[n])) {
 			swidth[wc] = src[n];
@@ -64,6 +64,9 @@ static SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src,
 	fmt[(n-start)+2] = '\0';
 	return n;
 }
+
+/* macro to `unsign' a character */
+#define uchar(c)	((unsigned SQChar)(c))
 
 SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output)
 {
@@ -82,7 +85,7 @@ SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen
 		}
 		else if(format[n+1] == '%') { //handles %%
 				dest[i++] = '%';
-				n += 2; 
+				n += 2;
 		}
 		else {
 			n++;
@@ -95,12 +98,69 @@ SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen
 			const SQChar *ts;
 			SQInteger ti;
 			SQFloat tf;
-			switch(format[n]) {
+			SQInteger fc = format[n];
+			switch(fc) {
+            case 'q':
 			case 's':
-				if(SQ_FAILED(sq_getstring(v,nparam,&ts))) 
+				if(SQ_FAILED(sq_getstring(v,nparam,&ts)))
 					return sq_throwerror(v,_SC("string expected for the specified format"));
-				addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar));
-				valtype = 's';
+                if(fc == 'q'){
+                    addlen = 2; //quotes before and after
+                    SQInteger size = sq_getsize(v,nparam);
+                    SQChar *ts2 = (SQChar*)ts;
+                      while (size--) {
+                        ++addlen;
+                        if (*ts2 == '"' || *ts2 == '\\' || *ts2 == '\n') {
+                          ++addlen;
+                        }
+                        else if (*ts2 == '\0' || iscntrl(uchar(*ts2))) {
+                          SQChar buff[10];
+                          if (!isdigit(uchar(*(ts2+1))))
+                            addlen += scsprintf(buff, "\\%d", (int)uchar(*ts2));
+                          else
+                            addlen += scsprintf(buff, "\\%03d", (int)uchar(*ts2));
+                        }
+                        ts2++;
+                      }
+
+                      ts2 = &dest[i];
+                      i += addlen;
+                      addlen = addlen*sizeof(SQChar);
+                      allocated += addlen + sizeof(SQChar);
+                      dest = sq_getscratchpad(v,allocated);
+
+                      size = sq_getsize(v,nparam);
+
+                      *ts2++ = '"';
+                      while (size--) {
+                        if (*ts == '"' || *ts == '\\' || *ts == '\n') {
+                            *ts2++ = '\\';
+                            *ts2++ = *ts;
+                        }
+                        else if (*ts == '\0' || iscntrl(uchar(*ts))) {
+                          SQChar buff[10];
+                          int iw;
+                          if (!isdigit(uchar(*(ts+1))))
+                            iw = scsprintf(buff, "\\%d", (int)uchar(*ts));
+                          else
+                            iw = scsprintf(buff, "\\%03d", (int)uchar(*ts));
+                          for(int i=0; i< iw; ++i) *ts2++ = buff[i];
+                        }
+                        else
+                            *ts2++ = *ts;
+                        ts++;
+                      }
+                      *ts2++ = '"';
+
+                      n++;
+                      nparam ++;
+                      continue;
+                }
+                else
+                {
+                    addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar));
+                    valtype = 's';
+                }
 				break;
 			case 'i': case 'd': case 'o': case 'u':  case 'x':  case 'X':
 #ifdef _SQ64
@@ -117,13 +177,13 @@ SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen
 				}
 #endif
 			case 'c':
-				if(SQ_FAILED(sq_getinteger(v,nparam,&ti))) 
+				if(SQ_FAILED(sq_getinteger(v,nparam,&ti)))
 					return sq_throwerror(v,_SC("integer expected for the specified format"));
 				addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
 				valtype = 'i';
 				break;
 			case 'f': case 'g': case 'G': case 'e':  case 'E':
-				if(SQ_FAILED(sq_getfloat(v,nparam,&tf))) 
+				if(SQ_FAILED(sq_getfloat(v,nparam,&tf)))
 					return sq_throwerror(v,_SC("float expected for the specified format"));
 				addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
 				valtype = 'f';
@@ -228,7 +288,7 @@ static SQInteger _string_split(HSQUIRRELVM v)
 
 #define SETUP_REX(v) \
 	SQRex *self = NULL; \
-	sq_getinstanceup(v,1,(SQUserPointer *)&self,0); 
+	sq_getinstanceup(v,1,(SQUserPointer *)&self,0);
 
 static SQInteger _rexobj_releasehook(SQUserPointer p, SQInteger size)
 {
@@ -250,6 +310,34 @@ static SQInteger _regexp_match(HSQUIRRELVM v)
 	sq_pushbool(v,SQFalse);
 	return 1;
 }
+
+static SQInteger _regexp_gmatch(HSQUIRRELVM v)
+{
+	SETUP_REX(v);
+	const SQChar *str;
+	SQInteger str_size;
+	sq_getstring(v,2,&str);
+	str_size = sq_getsize(v, 2);
+	const SQChar *begin,*end;
+	while(sqstd_rex_searchrange(self,str, str+str_size,&begin,&end)){
+	    SQInteger n = sqstd_rex_getsubexpcount(self);
+	    SQRexMatch match;
+	    sq_pushroottable(v); //this
+	    SQInteger i = 0;
+	    for(;i < n; i++) {
+            sqstd_rex_getsubexp(self,i,&match);
+            if(i > 0){ //skip whole match
+                sq_pushstring(v, match.begin, match.len);
+            }
+		}
+		i = sq_call(v, n, SQFalse, SQTrue);
+		if(i < 0) return i;
+		str_size -= end-str;
+		str = end;
+	}
+	sq_pushbool(v,SQFalse);
+	return 1;
+}
 
 static void _addrexmatch(HSQUIRRELVM v,const SQChar *str,const SQChar *begin,const SQChar *end)
 {
@@ -300,6 +388,41 @@ static SQInteger _regexp_capture(HSQUIRRELVM v)
 	return 0;
 }
 
+static SQInteger _regexp_xcapture(HSQUIRRELVM v)
+{
+	SETUP_REX(v);
+	const SQChar *str,*begin,*end;
+	SQInteger start = 0;
+	sq_getstring(v,2,&str);
+	if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
+	if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
+	    sq_pushbool(v, SQTrue);
+		return 1;
+	}
+	return 0;
+}
+
+static SQInteger _regexp_getxcapture(HSQUIRRELVM v)
+{
+	SETUP_REX(v);
+	SQInteger n, start;
+	const SQChar *str;
+	sq_getstring(v,2,&str);
+	sq_getinteger(v,3,&n);
+	SQRexMatch match;
+    sqstd_rex_getsubexp(self,n,&match);
+    if(match.len > 0){
+        start = match.begin-str;
+        sq_pushinteger(v, start);
+	    sq_arrayappend(v,-2);
+        sq_pushinteger(v, start+match.len);
+	    sq_arrayappend(v,-2);
+	    sq_pushbool(v, SQTrue);
+		return 1;
+    }
+	return 0;
+}
+
 static SQInteger _regexp_subexpcount(HSQUIRRELVM v)
 {
 	SETUP_REX(v);
@@ -329,7 +452,10 @@ static SQRegFunction rexobj_funcs[]={
 	_DECL_REX_FUNC(constructor,2,_SC(".s")),
 	_DECL_REX_FUNC(search,-2,_SC("xsn")),
 	_DECL_REX_FUNC(match,2,_SC("xs")),
+	_DECL_REX_FUNC(gmatch,3,_SC("xsc")),
 	_DECL_REX_FUNC(capture,-2,_SC("xsn")),
+	_DECL_REX_FUNC(xcapture,-2,_SC("xsn")),
+	_DECL_REX_FUNC(getxcapture,4,_SC("xsna")),
 	_DECL_REX_FUNC(subexpcount,1,_SC("x")),
 	_DECL_REX_FUNC(_typeof,1,_SC("x")),
 	{0,0}