Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

372 lines
8.9 KiB

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