Code::Blocks  SVN r11506
sqstdstring.cpp
Go to the documentation of this file.
1 /* see copyright notice in squirrel.h */
2 #include <squirrel.h>
3 #include <sqstdstring.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <ctype.h>
8 #include <assert.h>
9 
10 #ifdef SQUNICODE
11 #define scstrchr wcschr
12 #define scsnprintf wsnprintf
13 #define scatoi _wtoi
14 #define scstrtok wcstok
15 #else
16 #define scstrchr strchr
17 #define scsnprintf snprintf
18 #define scatoi atoi
19 #define scstrtok strtok
20 #endif
21 #define MAX_FORMAT_LEN 20
22 #define MAX_WFORMAT_LEN 3
23 #define ADDITIONAL_FORMAT_SPACE (100*sizeof(SQChar))
24 
25 static SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, SQInteger n,SQInteger &width)
26 {
27  SQChar swidth[MAX_WFORMAT_LEN];
28  SQInteger wc = 0;
29  SQInteger start = n;
30  fmt[0] = '%';
31  while (scstrchr(_SC("-+ #0"), src[n])) n++;
32  while (scisdigit(src[n])) {
33  swidth[wc] = src[n];
34  n++;
35  wc++;
36  if(wc>=MAX_WFORMAT_LEN)
37  return sq_throwerror(v,_SC("width format too long"));
38  }
39  swidth[wc] = '\0';
40  if(wc > 0) {
41  width = scatoi(swidth);
42  }
43  else
44  width = 0;
45  if (src[n] == '.') {
46  n++;
47 
48  wc = 0;
49  while (scisdigit(src[n])) {
50  swidth[wc] = src[n];
51  n++;
52  wc++;
53  if(wc>=MAX_WFORMAT_LEN)
54  return sq_throwerror(v,_SC("precision format too long"));
55  }
56  swidth[wc] = '\0';
57  if(wc > 0) {
58  width += scatoi(swidth);
59  }
60  }
61  if (n-start > MAX_FORMAT_LEN )
62  return sq_throwerror(v,_SC("format too long"));
63  memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(SQChar));
64  fmt[(n-start)+2] = '\0';
65  return n;
66 }
67 
68 
69 SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output)
70 {
71  const SQChar *format;
72  SQChar *dest;
74  sq_getstring(v,nformatstringidx,&format);
75  SQInteger allocated = (sq_getsize(v,nformatstringidx)+2)*sizeof(SQChar);
76  dest = sq_getscratchpad(v,allocated);
77  SQInteger n = 0,i = 0, nparam = nformatstringidx+1, w = 0;
78  while(format[n] != '\0') {
79  if(format[n] != '%') {
80  assert(i < allocated);
81  dest[i++] = format[n];
82  n++;
83  }
84  else if(format[n+1] == '%') { //handles %%
85  dest[i++] = '%';
86  n += 2;
87  }
88  else {
89  n++;
90  if( nparam > sq_gettop(v) )
91  // C::B patch: Correct misspelled "parameters"
92  return sq_throwerror(v,_SC("not enough parameters for the given format string"));
93  n = validate_format(v,fmt,format,n,w);
94  if(n < 0) return -1;
95  SQInteger addlen = 0;
96  SQInteger valtype = 0;
97  const SQChar *ts;
98  SQInteger ti;
99  SQFloat tf;
100  switch(format[n]) {
101  case 's':
102  if(SQ_FAILED(sq_getstring(v,nparam,&ts)))
103  return sq_throwerror(v,_SC("string expected for the specified format"));
104  addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar));
105  valtype = 's';
106  break;
107  case 'i': case 'd': case 'c':case 'o': case 'u': case 'x': case 'X':
108  if(SQ_FAILED(sq_getinteger(v,nparam,&ti)))
109  return sq_throwerror(v,_SC("integer expected for the specified format"));
110  addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
111  valtype = 'i';
112  break;
113  case 'f': case 'g': case 'G': case 'e': case 'E':
114  if(SQ_FAILED(sq_getfloat(v,nparam,&tf)))
115  return sq_throwerror(v,_SC("float expected for the specified format"));
116  addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
117  valtype = 'f';
118  break;
119  default:
120  return sq_throwerror(v,_SC("invalid format"));
121  }
122  n++;
123  allocated += addlen + sizeof(SQChar);
124  dest = sq_getscratchpad(v,allocated);
125  switch(valtype) {
126  case 's': i += scsprintf(&dest[i],fmt,ts); break;
127  case 'i': i += scsprintf(&dest[i],fmt,ti); break;
128  case 'f': i += scsprintf(&dest[i],fmt,tf); break;
129  };
130  nparam ++;
131  }
132  }
133  *outlen = i;
134  dest[i] = '\0';
135  *output = dest;
136  return SQ_OK;
137 }
138 
139 static SQInteger _string_format(HSQUIRRELVM v)
140 {
141  SQChar *dest = NULL;
142  SQInteger length = 0;
143  if(SQ_FAILED(sqstd_format(v,2,&length,&dest)))
144  return -1;
145  sq_pushstring(v,dest,length);
146  return 1;
147 }
148 
149 static void __strip_l(const SQChar *str,const SQChar **start)
150 {
151  const SQChar *t = str;
152  while(((*t) != '\0') && scisspace(*t)){ t++; }
153  *start = t;
154 }
155 
156 static void __strip_r(const SQChar *str,SQInteger len,const SQChar **end)
157 {
158  if(len == 0) {
159  *end = str;
160  return;
161  }
162  const SQChar *t = &str[len-1];
163  while(t != str && scisspace(*t)) { t--; }
164  *end = t+1;
165 }
166 
167 static SQInteger _string_strip(HSQUIRRELVM v)
168 {
169  const SQChar *str,*start,*end;
170  sq_getstring(v,2,&str);
171  SQInteger len = sq_getsize(v,2);
172  __strip_l(str,&start);
173  __strip_r(str,len,&end);
174  sq_pushstring(v,start,end - start);
175  return 1;
176 }
177 
178 static SQInteger _string_lstrip(HSQUIRRELVM v)
179 {
180  const SQChar *str,*start;
181  sq_getstring(v,2,&str);
182  __strip_l(str,&start);
183  sq_pushstring(v,start,-1);
184  return 1;
185 }
186 
187 static SQInteger _string_rstrip(HSQUIRRELVM v)
188 {
189  const SQChar *str,*end;
190  sq_getstring(v,2,&str);
191  SQInteger len = sq_getsize(v,2);
192  __strip_r(str,len,&end);
193  sq_pushstring(v,str,end - str);
194  return 1;
195 }
196 
197 static SQInteger _string_split(HSQUIRRELVM v)
198 {
199  const SQChar *str,*seps;
200  SQChar *stemp,*tok;
201  sq_getstring(v,2,&str);
202  sq_getstring(v,3,&seps);
203  if(sq_getsize(v,3) == 0) return sq_throwerror(v,_SC("empty separators string"));
204  SQInteger memsize = (sq_getsize(v,2)+1)*sizeof(SQChar);
205  stemp = sq_getscratchpad(v,memsize);
206  memcpy(stemp,str,memsize);
207  tok = scstrtok(stemp,seps);
208  sq_newarray(v,0);
209  while( tok != NULL ) {
210  sq_pushstring(v,tok,-1);
211  sq_arrayappend(v,-2);
212  tok = scstrtok( NULL, seps );
213  }
214  return 1;
215 }
216 
217 #define SETUP_REX(v) \
218  SQRex *self = NULL; \
219  sq_getinstanceup(v,1,(SQUserPointer *)&self,0);
220 
221 // C::B patch: Make the compiler happy by commenting unused variables
222 static SQInteger _rexobj_releasehook(SQUserPointer p, SQInteger /*size*/)
223 {
224  SQRex *self = ((SQRex *)p);
225  sqstd_rex_free(self);
226  return 1;
227 }
228 
229 static SQInteger _regexp_match(HSQUIRRELVM v)
230 {
231  SETUP_REX(v);
232  const SQChar *str;
233  sq_getstring(v,2,&str);
234  if(sqstd_rex_match(self,str) == SQTrue)
235  {
236  sq_pushbool(v,SQTrue);
237  return 1;
238  }
239  sq_pushbool(v,SQFalse);
240  return 1;
241 }
242 
243 static void _addrexmatch(HSQUIRRELVM v,const SQChar *str,const SQChar *begin,const SQChar *end)
244 {
245  sq_newtable(v);
246  sq_pushstring(v,_SC("begin"),-1);
247  sq_pushinteger(v,begin - str);
248  sq_rawset(v,-3);
249  sq_pushstring(v,_SC("end"),-1);
250  sq_pushinteger(v,end - str);
251  sq_rawset(v,-3);
252 }
253 
254 static SQInteger _regexp_search(HSQUIRRELVM v)
255 {
256  SETUP_REX(v);
257  const SQChar *str,*begin,*end;
258  SQInteger start = 0;
259  sq_getstring(v,2,&str);
260  if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
261  if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
262  _addrexmatch(v,str,begin,end);
263  return 1;
264  }
265  return 0;
266 }
267 
268 static SQInteger _regexp_capture(HSQUIRRELVM v)
269 {
270  SETUP_REX(v);
271  const SQChar *str,*begin,*end;
272  SQInteger start = 0;
273  sq_getstring(v,2,&str);
274  if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
275  if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
276  SQInteger n = sqstd_rex_getsubexpcount(self);
277  SQRexMatch match;
278  sq_newarray(v,0);
279  for(SQInteger i = 0;i < n; i++) {
280  sqstd_rex_getsubexp(self,i,&match);
281  if(match.len > 0)
282  _addrexmatch(v,str,match.begin,match.begin+match.len);
283  else
284  _addrexmatch(v,str,str,str); //empty match
285  sq_arrayappend(v,-2);
286  }
287  return 1;
288  }
289  return 0;
290 }
291 
292 static SQInteger _regexp_subexpcount(HSQUIRRELVM v)
293 {
294  SETUP_REX(v);
296  return 1;
297 }
298 
299 static SQInteger _regexp_constructor(HSQUIRRELVM v)
300 {
301  const SQChar *error,*pattern;
302  sq_getstring(v,2,&pattern);
303  SQRex *rex = sqstd_rex_compile(pattern,&error);
304  if(!rex) return sq_throwerror(v,error);
305  sq_setinstanceup(v,1,rex);
307  return 0;
308 }
309 
310 static SQInteger _regexp__typeof(HSQUIRRELVM v)
311 {
312  sq_pushstring(v,_SC("regexp"),-1);
313  return 1;
314 }
315 
316 #define _DECL_REX_FUNC(name,nparams,pmask) {_SC(#name),_regexp_##name,nparams,pmask}
317 static SQRegFunction rexobj_funcs[]={
318  _DECL_REX_FUNC(constructor,2,_SC(".s")),
319  _DECL_REX_FUNC(search,-2,_SC("xsn")),
320  _DECL_REX_FUNC(match,2,_SC("xs")),
321  _DECL_REX_FUNC(capture,-2,_SC("xsn")),
322  _DECL_REX_FUNC(subexpcount,1,_SC("x")),
323  _DECL_REX_FUNC(_typeof,1,_SC("x")),
324  {0,0}
325 };
326 
327 #define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask}
328 static SQRegFunction stringlib_funcs[]={
329  _DECL_FUNC(format,-2,_SC(".s")),
330  _DECL_FUNC(strip,2,_SC(".s")),
331  _DECL_FUNC(lstrip,2,_SC(".s")),
332  _DECL_FUNC(rstrip,2,_SC(".s")),
333  _DECL_FUNC(split,3,_SC(".ss")),
334  {0,0}
335 };
336 
337 
338 SQInteger sqstd_register_stringlib(HSQUIRRELVM v)
339 {
340  sq_pushstring(v,_SC("regexp"),-1);
341  sq_newclass(v,SQFalse);
342  SQInteger i = 0;
343  while(rexobj_funcs[i].name != 0) {
344  SQRegFunction &f = rexobj_funcs[i];
345  sq_pushstring(v,f.name,-1);
346  sq_newclosure(v,f.f,0);
347  sq_setparamscheck(v,f.nparamscheck,f.typemask);
348  sq_setnativeclosurename(v,-1,f.name);
349  sq_createslot(v,-3);
350  i++;
351  }
352  sq_createslot(v,-3);
353 
354  i = 0;
355  while(stringlib_funcs[i].name!=0)
356  {
357  sq_pushstring(v,stringlib_funcs[i].name,-1);
358  sq_newclosure(v,stringlib_funcs[i].f,0);
359  sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask);
361  sq_createslot(v,-3);
362  i++;
363  }
364  return 1;
365 }
SQRESULT sq_newclass(HSQUIRRELVM v, SQBool hasbase)
Definition: sqapi.cpp:239
static SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, SQInteger n, SQInteger &width)
Definition: sqstdstring.cpp:25
static void _addrexmatch(HSQUIRRELVM v, const SQChar *str, const SQChar *begin, const SQChar *end)
static SQInteger _regexp__typeof(HSQUIRRELVM v)
SQRESULT sq_throwerror(HSQUIRRELVM v, const SQChar *err)
Definition: sqapi.cpp:918
void sqstd_rex_free(SQRex *exp)
Definition: sqstdrex.cpp:578
void sq_newtable(HSQUIRRELVM v)
Definition: sqapi.cpp:229
SQRESULT sq_rawset(HSQUIRRELVM v, SQInteger idx)
Definition: sqapi.cpp:742
static void __strip_r(const SQChar *str, SQInteger len, const SQChar **end)
static SQInteger _regexp_subexpcount(HSQUIRRELVM v)
static void __strip_l(const SQChar *str, const SQChar **start)
#define scstrtok
Definition: sqstdstring.cpp:19
SQRESULT sq_arrayappend(HSQUIRRELVM v, SQInteger idx)
Definition: sqapi.cpp:263
SQRESULT sqstd_format(HSQUIRRELVM v, SQInteger nformatstringidx, SQInteger *outlen, SQChar **output)
Definition: sqstdstring.cpp:69
static SQInteger _string_rstrip(HSQUIRRELVM v)
#define ADDITIONAL_FORMAT_SPACE
Definition: sqstdstring.cpp:23
static SQRegFunction stringlib_funcs[]
#define SETUP_REX(v)
SQRESULT sq_getinteger(HSQUIRRELVM v, SQInteger idx, SQInteger *i)
Definition: sqapi.cpp:509
SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx)
Definition: sqapi.cpp:566
#define MAX_WFORMAT_LEN
Definition: sqstdstring.cpp:22
SQInteger sq_gettop(HSQUIRRELVM v)
Definition: sqapi.cpp:664
void sq_pushinteger(HSQUIRRELVM v, SQInteger n)
Definition: sqapi.cpp:202
void sq_newclosure(HSQUIRRELVM v, SQFUNCTION func, SQUnsignedInteger nfreevars)
Definition: sqapi.cpp:338
SQBool sqstd_rex_getsubexp(SQRex *exp, SQInteger n, SQRexMatch *subexp)
Definition: sqstdrex.cpp:640
#define MAX_FORMAT_LEN
Definition: sqstdstring.cpp:21
static SQRegFunction rexobj_funcs[]
static SQInteger _string_format(HSQUIRRELVM v)
SQRESULT sq_setnativeclosurename(HSQUIRRELVM v, SQInteger idx, const SQChar *name)
Definition: sqapi.cpp:362
static SQInteger _rexobj_releasehook(SQUserPointer p, SQInteger)
static SQInteger _regexp_capture(HSQUIRRELVM v)
static SQInteger _regexp_constructor(HSQUIRRELVM v)
static wxString capture
SQRESULT sq_getfloat(HSQUIRRELVM v, SQInteger idx, SQFloat *f)
Definition: sqapi.cpp:519
SQInteger sqstd_register_stringlib(HSQUIRRELVM v)
static SQInteger _string_strip(HSQUIRRELVM v)
static SQInteger _string_split(HSQUIRRELVM v)
SQRESULT sq_setparamscheck(HSQUIRRELVM v, SQInteger nparamscheck, const SQChar *typemask)
Definition: sqapi.cpp:373
SQRex * sqstd_rex_compile(const SQChar *pattern, const SQChar **error)
Definition: sqstdrex.cpp:533
void sq_pushstring(HSQUIRRELVM v, const SQChar *s, SQInteger len)
Definition: sqapi.cpp:195
SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p)
Definition: sqapi.cpp:629
SQRESULT sq_getstring(HSQUIRRELVM v, SQInteger idx, const SQChar **c)
Definition: sqapi.cpp:539
char SQChar
static SQInteger _string_lstrip(HSQUIRRELVM v)
SQBool sqstd_rex_match(SQRex *exp, const SQChar *text)
Definition: sqstdrex.cpp:588
#define _DECL_REX_FUNC(name, nparams, pmask)
void sq_pushbool(HSQUIRRELVM v, SQBool b)
Definition: sqapi.cpp:207
void sq_newarray(HSQUIRRELVM v, SQInteger size)
Definition: sqapi.cpp:234
SQChar * sq_getscratchpad(HSQUIRRELVM v, SQInteger minsize)
Definition: sqapi.cpp:1044
SQInteger sqstd_rex_getsubexpcount(SQRex *exp)
Definition: sqstdrex.cpp:635
static SQInteger _regexp_match(HSQUIRRELVM v)
void sq_setreleasehook(HSQUIRRELVM v, SQInteger idx, SQRELEASEHOOK hook)
Definition: sqapi.cpp:999
#define scstrchr
Definition: sqstdstring.cpp:16
#define NULL
Definition: prefix.cpp:59
#define scatoi
Definition: sqstdstring.cpp:18
#define _DECL_FUNC(name, nparams, pmask)