Advertisement
Guest User

Untitled

a guest
Aug 11th, 2013
206
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 33.89 KB | None | 0 0
  1. #include "stdafx.h"
  2.  
  3. #include "ScriptWString.h"
  4. #include <assert.h> // assert()
  5. #include <sstream> // std::stringstream
  6. #include <string.h> // strstr()
  7. #include <stdio.h> // sprintf()
  8. #include <stdlib.h> // strtod()
  9. #include <locale.h> // setlocale()
  10. #include <map> // std::map
  11.  
  12. using namespace std;
  13.  
  14. BEGIN_AS_NAMESPACE
  15.  
  16. #if AS_USE_STRINGPOOL == 1
  17.  
  18. // By keeping the literal strings in a pool the application
  19. // performance is improved as there are less string copies created.
  20.  
  21. // The string pool will be kept as user data in the engine. We'll
  22. // need a specific type to identify the string pool user data.
  23. // We just define a number here that we assume nobody else is using for
  24. // object type user data. The add-ons have reserved the numbers 1000
  25. // through 1999 for this purpose, so we should be fine.
  26. const asPWORD STRING_POOL = 1001;
  27.  
  28. static const wstring &StringFactory(asUINT length, const wchar_t *s)
  29. {
  30. static wstring dummy;
  31.  
  32. // Each engine instance has its own string pool
  33. asIScriptContext *ctx = asGetActiveContext();
  34. if( ctx == 0 )
  35. {
  36. // The string factory can only be called from a script
  37. assert( ctx );
  38. return dummy;
  39. }
  40. asIScriptEngine *engine = ctx->GetEngine();
  41.  
  42. // TODO: runtime optimize: Use unordered_map if C++11 is supported, i.e. MSVC10+, gcc 4.?+
  43. map<const wchar_t *, wstring> *pool = reinterpret_cast< map<const wchar_t *, wstring>* >(engine->GetUserData(STRING_POOL));
  44.  
  45. if( !pool )
  46. {
  47. // The string pool hasn't been created yet, so we'll create it now
  48. asAcquireExclusiveLock();
  49.  
  50. // Make sure the string pool wasn't created while we were waiting for the lock
  51. pool = reinterpret_cast< map<const wchar_t *, wstring>* >(engine->GetUserData(STRING_POOL));
  52. if( !pool )
  53. {
  54. #if defined(AS_MARMALADE)
  55. pool = new map<const wchar_t *, wstring>;
  56. #else
  57. pool = new (nothrow) map<const wchar_t *, wstring>;
  58. #endif
  59. if( pool == 0 )
  60. {
  61. ctx->SetException("Out of memory");
  62. asReleaseExclusiveLock();
  63. return dummy;
  64. }
  65. engine->SetUserData(pool, STRING_POOL);
  66. }
  67.  
  68. asReleaseExclusiveLock();
  69. }
  70.  
  71. // We can't let other threads modify the pool while we query it
  72. asAcquireSharedLock();
  73.  
  74. // First check if a string object hasn't been created already
  75. map<const wchar_t *, wstring>::iterator it;
  76. it = pool->find(s);
  77. if( it != pool->end() )
  78. {
  79. asReleaseSharedLock();
  80. return it->second;
  81. }
  82.  
  83. asReleaseSharedLock();
  84.  
  85. // Acquire an exclusive lock so we can add the new string to the pool
  86. asAcquireExclusiveLock();
  87.  
  88. // Make sure the string wasn't created while we were waiting for the exclusive lock
  89. it = pool->find(s);
  90. if( it == pool->end() )
  91. {
  92. // Create a new string object
  93. // Divide length in 2 for wstring
  94. pool->insert(map<const wchar_t *, wstring>::value_type(s, wstring(s, length/2)));
  95. it = pool->find(s);
  96. }
  97.  
  98. asReleaseExclusiveLock();
  99. return it->second;
  100. }
  101.  
  102. static void CleanupEngineStringPool(asIScriptEngine *engine)
  103. {
  104. map<const wchar_t *, wstring> *pool = reinterpret_cast< map<const wchar_t *, wstring>* >(engine->GetUserData(STRING_POOL));
  105. if( pool )
  106. delete pool;
  107. }
  108.  
  109. #else
  110. static wstring StringFactory(asUINT length, const wchar_t *s)
  111. {
  112. return wstring(s, length/2);
  113. }
  114. #endif
  115.  
  116. static void ConstructString(wstring *thisPointer)
  117. {
  118. new(thisPointer) wstring();
  119. }
  120.  
  121. static void CopyConstructString(const wstring &other, wstring *thisPointer)
  122. {
  123. new(thisPointer) wstring(other);
  124. }
  125.  
  126. static void DestructString(wstring *thisPointer)
  127. {
  128. thisPointer->~wstring();
  129. }
  130.  
  131. static wstring &AssignUIntToString(unsigned int i, wstring &dest)
  132. {
  133. wostringstream stream;
  134. stream << i;
  135. dest = stream.str();
  136. return dest;
  137. }
  138.  
  139. static wstring &AddAssignUIntToString(unsigned int i, wstring &dest)
  140. {
  141. wostringstream stream;
  142. stream << i;
  143. dest += stream.str();
  144. return dest;
  145. }
  146.  
  147. static wstring AddStringUInt(const wstring &str, unsigned int i)
  148. {
  149. wostringstream stream;
  150. stream << i;
  151. return str + stream.str();
  152. }
  153.  
  154. static wstring AddIntString(int i, const wstring &str)
  155. {
  156. wostringstream stream;
  157. stream << i;
  158. return stream.str() + str;
  159. }
  160.  
  161. static wstring &AssignIntToString(int i, wstring &dest)
  162. {
  163. wostringstream stream;
  164. stream << i;
  165. dest = stream.str();
  166. return dest;
  167. }
  168.  
  169. static wstring &AddAssignIntToString(int i, wstring &dest)
  170. {
  171. wostringstream stream;
  172. stream << i;
  173. dest += stream.str();
  174. return dest;
  175. }
  176.  
  177. static wstring AddStringInt(const wstring &str, int i)
  178. {
  179. wostringstream stream;
  180. stream << i;
  181. return str + stream.str();
  182. }
  183.  
  184. static wstring AddUIntString(unsigned int i, const wstring &str)
  185. {
  186. wostringstream stream;
  187. stream << i;
  188. return stream.str() + str;
  189. }
  190.  
  191. static wstring &AssignDoubleToString(double f, wstring &dest)
  192. {
  193. wostringstream stream;
  194. stream << f;
  195. dest = stream.str();
  196. return dest;
  197. }
  198.  
  199. static wstring &AddAssignDoubleToString(double f, wstring &dest)
  200. {
  201. wostringstream stream;
  202. stream << f;
  203. dest += stream.str();
  204. return dest;
  205. }
  206.  
  207. static wstring &AssignBoolToString(bool b, wstring &dest)
  208. {
  209. wostringstream stream;
  210. stream << (b ? "true" : "false");
  211. dest = stream.str();
  212. return dest;
  213. }
  214.  
  215. static wstring &AddAssignBoolToString(bool b, wstring &dest)
  216. {
  217. wostringstream stream;
  218. stream << (b ? "true" : "false");
  219. dest += stream.str();
  220. return dest;
  221. }
  222.  
  223. static wstring AddStringDouble(const wstring &str, double f)
  224. {
  225. wostringstream stream;
  226. stream << f;
  227. return str + stream.str();
  228. }
  229.  
  230. static wstring AddDoubleString(double f, const wstring &str)
  231. {
  232. wostringstream stream;
  233. stream << f;
  234. return stream.str() + str;
  235. }
  236.  
  237. static wstring AddStringBool(const wstring &str, bool b)
  238. {
  239. wostringstream stream;
  240. stream << (b ? "true" : "false");
  241. return str + stream.str();
  242. }
  243.  
  244. static wstring AddBoolString(bool b, const wstring &str)
  245. {
  246. wostringstream stream;
  247. stream << (b ? "true" : "false");
  248. return stream.str() + str;
  249. }
  250.  
  251. static wchar_t *StringCharAt(unsigned int i, wstring &str)
  252. {
  253. if( i >= str.size() )
  254. {
  255. // Set a script exception
  256. asIScriptContext *ctx = asGetActiveContext();
  257. ctx->SetException("Out of range");
  258.  
  259. // Return a null pointer
  260. return 0;
  261. }
  262.  
  263. return &str[i];
  264. }
  265.  
  266. // AngelScript signature:
  267. // int wstring::opCmp(const wstring &in) const
  268. static int StringCmp(const wstring &a, const wstring &b)
  269. {
  270. int cmp = 0;
  271. if( a < b ) cmp = -1;
  272. else if( a > b ) cmp = 1;
  273. return cmp;
  274. }
  275.  
  276. // This function returns the index of the first position where the substring
  277. // exists in the input string. If the substring doesn't exist in the input
  278. // string -1 is returned.
  279. //
  280. // AngelScript signature:
  281. // int wstring::findFirst(const wstring &in sub, uint start = 0) const
  282. static int StringFindFirst(const wstring &sub, asUINT start, const wstring &str)
  283. {
  284. // We don't register the method directly because the argument types change between 32bit and 64bit platforms
  285. return (int)str.find(sub, start);
  286. }
  287.  
  288. // This function returns the index of the last position where the substring
  289. // exists in the input string. If the substring doesn't exist in the input
  290. // string -1 is returned.
  291. //
  292. // AngelScript signature:
  293. // int wstring::findLast(const wstring &in sub, int start = -1) const
  294. static int StringFindLast(const wstring &sub, int start, const wstring &str)
  295. {
  296. // We don't register the method directly because the argument types change between 32bit and 64bit platforms
  297. return (int)str.rfind(sub, (size_t)start);
  298. }
  299.  
  300. // AngelScript signature:
  301. // uint wstring::length() const
  302. static asUINT StringLength(const wstring &str)
  303. {
  304. // We don't register the method directly because the return type changes between 32bit and 64bit platforms
  305. return (asUINT)str.length();
  306. }
  307.  
  308.  
  309. // AngelScript signature:
  310. // void wstring::resize(uint l)
  311. static void StringResize(asUINT l, wstring &str)
  312. {
  313. // We don't register the method directly because the argument types change between 32bit and 64bit platforms
  314. str.resize(l);
  315. }
  316.  
  317. // AngelScript signature:
  318. // wstring formatInt(int64 val, const wstring &in options, uint width)
  319. static wstring formatInt(asINT64 value, const wstring &options, asUINT width)
  320. {
  321. bool leftJustify = options.find(L"l") != -1;
  322. bool padWithZero = options.find(L"0") != -1;
  323. bool alwaysSign = options.find(L"+") != -1;
  324. bool spaceOnSign = options.find(L" ") != -1;
  325. bool hexSmall = options.find(L"h") != -1;
  326. bool hexLarge = options.find(L"H") != -1;
  327.  
  328. wstring fmt = L"%";
  329. if( leftJustify ) fmt += L"-";
  330. if( alwaysSign ) fmt += L"+";
  331. if( spaceOnSign ) fmt += L" ";
  332. if( padWithZero ) fmt += L"0";
  333.  
  334. #ifdef __GNUC__
  335. #ifdef _LP64
  336. fmt += L"*l";
  337. #else
  338. fmt += L"*ll";
  339. #endif
  340. #else
  341. fmt += L"*I64";
  342. #endif
  343.  
  344. if( hexSmall ) fmt += L"x";
  345. else if( hexLarge ) fmt += L"X";
  346. else fmt += L"d";
  347.  
  348. wstring buf;
  349. buf.resize(width+20);
  350. #if _MSC_VER >= 1400 && !defined(AS_MARMALADE)// MSVC 8.0 / 2005
  351. swprintf_s(&buf[0], buf.size(), fmt.c_str(), width, value);
  352. #else
  353. sprintf(&buf[0], fmt.c_str(), width, value);
  354. #endif
  355. buf.resize(wcslen(&buf[0]));
  356.  
  357. return buf;
  358. }
  359.  
  360. // AngelScript signature:
  361. // wstring formatFloat(double val, const wstring &in options, uint width, uint precision)
  362. static wstring formatFloat(double value, const wstring &options, asUINT width, asUINT precision)
  363. {
  364. bool leftJustify = options.find(L"l") != -1;
  365. bool padWithZero = options.find(L"0") != -1;
  366. bool alwaysSign = options.find(L"+") != -1;
  367. bool spaceOnSign = options.find(L" ") != -1;
  368. bool expSmall = options.find(L"e") != -1;
  369. bool expLarge = options.find(L"E") != -1;
  370.  
  371. wstring fmt = L"%";
  372. if( leftJustify ) fmt += L"-";
  373. if( alwaysSign ) fmt += L"+";
  374. if( spaceOnSign ) fmt += L" ";
  375. if( padWithZero ) fmt += L"0";
  376.  
  377. fmt += L"*.*";
  378.  
  379. if( expSmall ) fmt += L"e";
  380. else if( expLarge ) fmt += L"E";
  381. else fmt += L"f";
  382.  
  383. wstring buf;
  384. buf.resize(width+precision+50);
  385. #if _MSC_VER >= 1400 && !defined(AS_MARMALADE)// MSVC 8.0 / 2005
  386. swprintf_s(&buf[0], buf.size(), fmt.c_str(), width, precision, value);
  387. #else
  388. swprintf(&buf[0], fmt.c_str(), width, precision, value);
  389. #endif
  390. buf.resize(wcslen(&buf[0]));
  391.  
  392. return buf;
  393. }
  394.  
  395. // AngelScript signature:
  396. // int64 parseInt(const wstring &in val, uint base = 10, uint &out byteCount = 0)
  397. static asINT64 parseInt(const wstring &val, asUINT base, asUINT *byteCount)
  398. {
  399. // Only accept base 10 and 16
  400. if( base != 10 && base != 16 )
  401. {
  402. if( byteCount ) *byteCount = 0;
  403. return 0;
  404. }
  405.  
  406. const wchar_t *end = &val[0];
  407.  
  408. // Determine the sign
  409. bool sign = false;
  410. if( *end == '-' )
  411. {
  412. sign = true;
  413. *end++;
  414. }
  415. else if( *end == '+' )
  416. *end++;
  417.  
  418. asINT64 res = 0;
  419. if( base == 10 )
  420. {
  421. while( *end >= '0' && *end <= '9' )
  422. {
  423. res *= 10;
  424. res += *end++ - '0';
  425. }
  426. }
  427. else if( base == 16 )
  428. {
  429. while( (*end >= '0' && *end <= '9') ||
  430. (*end >= 'a' && *end <= 'f') ||
  431. (*end >= 'A' && *end <= 'F') )
  432. {
  433. res *= 16;
  434. if( *end >= '0' && *end <= '9' )
  435. res += *end++ - '0';
  436. else if( *end >= 'a' && *end <= 'f' )
  437. res += *end++ - 'a' + 10;
  438. else if( *end >= 'A' && *end <= 'F' )
  439. res += *end++ - 'A' + 10;
  440. }
  441. }
  442.  
  443. if( byteCount )
  444. *byteCount = asUINT(size_t(end - val.c_str()));
  445.  
  446. if( sign )
  447. res = -res;
  448.  
  449. return res;
  450. }
  451.  
  452. // AngelScript signature:
  453. // double parseFloat(const wstring &in val, uint &out byteCount = 0)
  454. double parseFloat(const wstring &val, asUINT *byteCount)
  455. {
  456. char *end;
  457.  
  458. // WinCE doesn't have setlocale. Some quick testing on my current platform
  459. // still manages to parse the numbers such as "3.14" even if the decimal for the
  460. // locale is ",".
  461. #if !defined(_WIN32_WCE) && !defined(ANDROID)
  462. // Set the locale to C so that we are guaranteed to parse the float value correctly
  463. char *orig = setlocale(LC_NUMERIC, 0);
  464. setlocale(LC_NUMERIC, "C");
  465. #endif
  466.  
  467. // Used wstring->string conversion here:
  468. std::string tmpstring(val.begin(),val.end());
  469. double res = strtod(tmpstring.c_str(), &end);
  470.  
  471. #if !defined(_WIN32_WCE) && !defined(ANDROID)
  472. // Restore the locale
  473. setlocale(LC_NUMERIC, orig);
  474. #endif
  475.  
  476. // returned letter count here, not 'bytes'
  477. if( byteCount )
  478. *byteCount = asUINT(size_t(end - tmpstring.c_str()));
  479.  
  480. return res;
  481. }
  482.  
  483. // This function returns a string containing the substring of the input string
  484. // determined by the starting index and count of characters.
  485. //
  486. // AngelScript signature:
  487. // wstring wstring::substr(uint start = 0, int count = -1) const
  488. static wstring StringSubString(asUINT start, int count, const wstring &str)
  489. {
  490. // Check for out-of-bounds
  491. wstring ret;
  492. if( start < str.length() && count != 0 )
  493. ret = str.substr(start, count);
  494.  
  495. return ret;
  496. }
  497.  
  498. void RegisterStdWString_Native(asIScriptEngine *engine)
  499. {
  500. int r;
  501.  
  502.  
  503. // Register the string type
  504. r = engine->RegisterObjectType("string", sizeof(wstring), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert( r >= 0 );
  505.  
  506. #if AS_USE_STRINGPOOL == 1
  507. // Register the string factory
  508. r = engine->RegisterStringFactory("const string &", asFUNCTION(StringFactory), asCALL_CDECL); assert( r >= 0 );
  509.  
  510. // Register the cleanup callback for the string pool
  511. engine->SetEngineUserDataCleanupCallback(CleanupEngineStringPool, STRING_POOL);
  512. #else
  513. // Register the string factory
  514. r = engine->RegisterStringFactory("string", asFUNCTION(StringFactory), asCALL_CDECL); assert( r >= 0 );
  515. #endif
  516.  
  517. // Register the object operator overloads
  518. r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  519. r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f(const string &in)", asFUNCTION(CopyConstructString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  520. r = engine->RegisterObjectBehaviour("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  521. r = engine->RegisterObjectMethod("string", "string &opAssign(const string &in)", asMETHODPR(wstring, operator =, (const wstring&), wstring&), asCALL_THISCALL); assert( r >= 0 );
  522. r = engine->RegisterObjectMethod("string", "string &opAddAssign(const string &in)", asMETHODPR(wstring, operator+=, (const wstring&), wstring&), asCALL_THISCALL); assert( r >= 0 );
  523.  
  524. r = engine->RegisterObjectMethod("string", "bool opEquals(const string &in) const", asFUNCTIONPR(operator ==, (const wstring &, const wstring &), bool), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
  525. r = engine->RegisterObjectMethod("string", "int opCmp(const string &in) const", asFUNCTION(StringCmp), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
  526. r = engine->RegisterObjectMethod("string", "string opAdd(const string &in) const", asFUNCTIONPR(operator +, (const wstring &, const wstring &), wstring), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
  527.  
  528. // The string length can be accessed through methods or through virtual property
  529. r = engine->RegisterObjectMethod("string", "uint length() const", asFUNCTION(StringLength), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  530. r = engine->RegisterObjectMethod("string", "void resize(uint)", asFUNCTION(StringResize), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  531. r = engine->RegisterObjectMethod("string", "uint get_length() const", asFUNCTION(StringLength), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  532. r = engine->RegisterObjectMethod("string", "void set_length(uint)", asFUNCTION(StringResize), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  533. r = engine->RegisterObjectMethod("string", "bool isEmpty() const", asMETHOD(wstring, empty), asCALL_THISCALL); assert( r >= 0 );
  534.  
  535. // Register the index operator, both as a mutator and as an inspector
  536. // Note that we don't register the operator[] directly, as it doesn't do bounds checking
  537. r = engine->RegisterObjectMethod("string", "uint8 &opIndex(uint)", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  538. r = engine->RegisterObjectMethod("string", "const uint8 &opIndex(uint) const", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  539.  
  540. // Automatic conversion from values
  541. r = engine->RegisterObjectMethod("string", "string &opAssign(double)", asFUNCTION(AssignDoubleToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  542. r = engine->RegisterObjectMethod("string", "string &opAddAssign(double)", asFUNCTION(AddAssignDoubleToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  543. r = engine->RegisterObjectMethod("string", "string opAdd(double) const", asFUNCTION(AddStringDouble), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
  544. r = engine->RegisterObjectMethod("string", "string opAdd_r(double) const", asFUNCTION(AddDoubleString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  545.  
  546. r = engine->RegisterObjectMethod("string", "string &opAssign(int)", asFUNCTION(AssignIntToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  547. r = engine->RegisterObjectMethod("string", "string &opAddAssign(int)", asFUNCTION(AddAssignIntToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  548. r = engine->RegisterObjectMethod("string", "string opAdd(int) const", asFUNCTION(AddStringInt), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
  549. r = engine->RegisterObjectMethod("string", "string opAdd_r(int) const", asFUNCTION(AddIntString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  550.  
  551. r = engine->RegisterObjectMethod("string", "string &opAssign(uint)", asFUNCTION(AssignUIntToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  552. r = engine->RegisterObjectMethod("string", "string &opAddAssign(uint)", asFUNCTION(AddAssignUIntToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  553. r = engine->RegisterObjectMethod("string", "string opAdd(uint) const", asFUNCTION(AddStringUInt), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
  554. r = engine->RegisterObjectMethod("string", "string opAdd_r(uint) const", asFUNCTION(AddUIntString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  555.  
  556. r = engine->RegisterObjectMethod("string", "string &opAssign(bool)", asFUNCTION(AssignBoolToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  557. r = engine->RegisterObjectMethod("string", "string &opAddAssign(bool)", asFUNCTION(AddAssignBoolToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  558. r = engine->RegisterObjectMethod("string", "string opAdd(bool) const", asFUNCTION(AddStringBool), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
  559. r = engine->RegisterObjectMethod("string", "string opAdd_r(bool) const", asFUNCTION(AddBoolString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  560.  
  561. // Utilities
  562. r = engine->RegisterObjectMethod("string", "string substr(uint start = 0, int count = -1) const", asFUNCTION(StringSubString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  563. r = engine->RegisterObjectMethod("string", "int findFirst(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  564. r = engine->RegisterObjectMethod("string", "int findLast(const string &in, int start = -1) const", asFUNCTION(StringFindLast), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  565.  
  566. r = engine->RegisterGlobalFunction("string formatInt(int64 val, const string &in options, uint width = 0)", asFUNCTION(formatInt), asCALL_CDECL); assert(r >= 0);
  567. r = engine->RegisterGlobalFunction("string formatFloat(double val, const string &in options, uint width = 0, uint precision = 0)", asFUNCTION(formatFloat), asCALL_CDECL); assert(r >= 0);
  568. r = engine->RegisterGlobalFunction("int64 parseInt(const string &in, uint base = 10, uint &out byteCount = 0)", asFUNCTION(parseInt), asCALL_CDECL); assert(r >= 0);
  569. r = engine->RegisterGlobalFunction("double parseFloat(const string &in, uint &out byteCount = 0)", asFUNCTION(parseFloat), asCALL_CDECL); assert(r >= 0);
  570.  
  571. #if AS_USE_STLNAMES == 1
  572. // Same as length
  573. r = engine->RegisterObjectMethod("string", "uint size() const", asFUNCTION(StringLength), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  574. // Same as isEmpty
  575. r = engine->RegisterObjectMethod("string", "bool empty() const", asMETHOD(wstring, empty), asCALL_THISCALL); assert( r >= 0 );
  576. // Same as findFirst
  577. r = engine->RegisterObjectMethod("string", "int find(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  578. // Same as findLast
  579. r = engine->RegisterObjectMethod("string", "int rfind(const string &in, int start = -1) const", asFUNCTION(StringFindLast), asCALL_CDECL_OBJLAST); assert( r >= 0 );
  580. #endif
  581.  
  582. // TODO: Implement the following
  583. // findFirstOf
  584. // findLastOf
  585. // findFirstNotOf
  586. // findLastNotOf
  587. // findAndReplace - replaces a text found in the string
  588. // replaceRange - replaces a range of bytes in the string
  589. // trim/trimLeft/trimRight
  590. // multiply/times/opMul/opMul_r - takes the string and multiplies it n times, e.g. "-".multiply(5) returns "-----"
  591. }
  592.  
  593. #if AS_USE_STRINGPOOL == 1
  594. static void StringFactoryGeneric(asIScriptGeneric *gen) {
  595. asUINT length = gen->GetArgDWord(0);
  596. const wchar_t *s = (const wchar_t*)gen->GetArgAddress(1);
  597.  
  598. // Return a reference to a string
  599. gen->SetReturnAddress(const_cast<wstring*>(&StringFactory(length/2, s)));
  600. }
  601. #else
  602. static void StringFactoryGeneric(asIScriptGeneric *gen) {
  603. asUINT length = gen->GetArgDWord(0);
  604. const wchar_t *s = (const wchar_t*)gen->GetArgAddress(1);
  605.  
  606. // Return a string value
  607. new (gen->GetAddressOfReturnLocation()) wstring(StringFactory(length/2, s));
  608. }
  609. #endif
  610.  
  611. static void ConstructStringGeneric(asIScriptGeneric * gen) {
  612. new (gen->GetObject()) wstring();
  613. }
  614.  
  615. static void CopyConstructStringGeneric(asIScriptGeneric * gen) {
  616. wstring * a = static_cast<wstring *>(gen->GetArgObject(0));
  617. new (gen->GetObject()) wstring(*a);
  618. }
  619.  
  620. static void DestructStringGeneric(asIScriptGeneric * gen) {
  621. wstring * ptr = static_cast<wstring *>(gen->GetObject());
  622. ptr->~wstring();
  623. }
  624.  
  625. static void AssignStringGeneric(asIScriptGeneric *gen) {
  626. wstring * a = static_cast<wstring *>(gen->GetArgObject(0));
  627. wstring * self = static_cast<wstring *>(gen->GetObject());
  628. *self = *a;
  629. gen->SetReturnAddress(self);
  630. }
  631.  
  632. static void AddAssignStringGeneric(asIScriptGeneric *gen) {
  633. wstring * a = static_cast<wstring *>(gen->GetArgObject(0));
  634. wstring * self = static_cast<wstring *>(gen->GetObject());
  635. *self += *a;
  636. gen->SetReturnAddress(self);
  637. }
  638.  
  639. static void StringEqualsGeneric(asIScriptGeneric * gen) {
  640. wstring * a = static_cast<wstring *>(gen->GetObject());
  641. wstring * b = static_cast<wstring *>(gen->GetArgAddress(0));
  642. *(bool*)gen->GetAddressOfReturnLocation() = (*a == *b);
  643. }
  644.  
  645. static void StringCmpGeneric(asIScriptGeneric * gen) {
  646. wstring * a = static_cast<wstring *>(gen->GetObject());
  647. wstring * b = static_cast<wstring *>(gen->GetArgAddress(0));
  648.  
  649. int cmp = 0;
  650. if( *a < *b ) cmp = -1;
  651. else if( *a > *b ) cmp = 1;
  652.  
  653. *(int*)gen->GetAddressOfReturnLocation() = cmp;
  654. }
  655.  
  656. static void StringAddGeneric(asIScriptGeneric * gen) {
  657. wstring * a = static_cast<wstring *>(gen->GetObject());
  658. wstring * b = static_cast<wstring *>(gen->GetArgAddress(0));
  659. wstring ret_val = *a + *b;
  660. gen->SetReturnObject(&ret_val);
  661. }
  662.  
  663. static void StringLengthGeneric(asIScriptGeneric * gen) {
  664. wstring * self = static_cast<wstring *>(gen->GetObject());
  665. *static_cast<asUINT *>(gen->GetAddressOfReturnLocation()) = (asUINT)self->length();
  666. }
  667.  
  668. static void StringResizeGeneric(asIScriptGeneric * gen) {
  669. wstring * self = static_cast<wstring *>(gen->GetObject());
  670. self->resize(*static_cast<asUINT *>(gen->GetAddressOfArg(0)));
  671. }
  672.  
  673. static void StringCharAtGeneric(asIScriptGeneric * gen) {
  674. unsigned int index = gen->GetArgDWord(0);
  675. wstring * self = static_cast<wstring *>(gen->GetObject());
  676.  
  677. if (index >= self->size()) {
  678. // Set a script exception
  679. asIScriptContext *ctx = asGetActiveContext();
  680. ctx->SetException("Out of range");
  681.  
  682. gen->SetReturnAddress(0);
  683. } else {
  684. gen->SetReturnAddress(&(self->operator [](index)));
  685. }
  686. }
  687.  
  688. static void AssignInt2StringGeneric(asIScriptGeneric *gen)
  689. {
  690. int *a = static_cast<int*>(gen->GetAddressOfArg(0));
  691. wstring *self = static_cast<wstring*>(gen->GetObject());
  692. std::wstringstream sstr;
  693. sstr << *a;
  694. *self = sstr.str();
  695. gen->SetReturnAddress(self);
  696. }
  697.  
  698. static void AssignUInt2StringGeneric(asIScriptGeneric *gen)
  699. {
  700. unsigned int *a = static_cast<unsigned int*>(gen->GetAddressOfArg(0));
  701. wstring *self = static_cast<wstring*>(gen->GetObject());
  702. std::wstringstream sstr;
  703. sstr << *a;
  704. *self = sstr.str();
  705. gen->SetReturnAddress(self);
  706. }
  707.  
  708. static void AssignDouble2StringGeneric(asIScriptGeneric *gen)
  709. {
  710. double *a = static_cast<double*>(gen->GetAddressOfArg(0));
  711. wstring *self = static_cast<wstring*>(gen->GetObject());
  712. std::wstringstream sstr;
  713. sstr << *a;
  714. *self = sstr.str();
  715. gen->SetReturnAddress(self);
  716. }
  717.  
  718. static void AssignBool2StringGeneric(asIScriptGeneric *gen)
  719. {
  720. bool *a = static_cast<bool*>(gen->GetAddressOfArg(0));
  721. wstring *self = static_cast<wstring*>(gen->GetObject());
  722. std::wstringstream sstr;
  723. sstr << (*a ? "true" : "false");
  724. *self = sstr.str();
  725. gen->SetReturnAddress(self);
  726. }
  727.  
  728. static void AddAssignDouble2StringGeneric(asIScriptGeneric * gen) {
  729. double * a = static_cast<double *>(gen->GetAddressOfArg(0));
  730. wstring * self = static_cast<wstring *>(gen->GetObject());
  731. std::wstringstream sstr;
  732. sstr << *a;
  733. *self += sstr.str();
  734. gen->SetReturnAddress(self);
  735. }
  736.  
  737. static void AddAssignInt2StringGeneric(asIScriptGeneric * gen) {
  738. int * a = static_cast<int *>(gen->GetAddressOfArg(0));
  739. wstring * self = static_cast<wstring *>(gen->GetObject());
  740. std::wstringstream sstr;
  741. sstr << *a;
  742. *self += sstr.str();
  743. gen->SetReturnAddress(self);
  744. }
  745.  
  746. static void AddAssignUInt2StringGeneric(asIScriptGeneric * gen) {
  747. unsigned int * a = static_cast<unsigned int *>(gen->GetAddressOfArg(0));
  748. wstring * self = static_cast<wstring *>(gen->GetObject());
  749. std::wstringstream sstr;
  750. sstr << *a;
  751. *self += sstr.str();
  752. gen->SetReturnAddress(self);
  753. }
  754.  
  755. static void AddAssignBool2StringGeneric(asIScriptGeneric * gen) {
  756. bool * a = static_cast<bool *>(gen->GetAddressOfArg(0));
  757. wstring * self = static_cast<wstring *>(gen->GetObject());
  758. std::wstringstream sstr;
  759. sstr << (*a ? "true" : "false");
  760. *self += sstr.str();
  761. gen->SetReturnAddress(self);
  762. }
  763.  
  764. static void AddString2DoubleGeneric(asIScriptGeneric * gen) {
  765. wstring * a = static_cast<wstring *>(gen->GetObject());
  766. double * b = static_cast<double *>(gen->GetAddressOfArg(0));
  767. std::wstringstream sstr;
  768. sstr << *a << *b;
  769. std::wstring ret_val = sstr.str();
  770. gen->SetReturnObject(&ret_val);
  771. }
  772.  
  773. static void AddString2IntGeneric(asIScriptGeneric * gen) {
  774. wstring * a = static_cast<wstring *>(gen->GetObject());
  775. int * b = static_cast<int *>(gen->GetAddressOfArg(0));
  776. std::wstringstream sstr;
  777. sstr << *a << *b;
  778. std::wstring ret_val = sstr.str();
  779. gen->SetReturnObject(&ret_val);
  780. }
  781.  
  782. static void AddString2UIntGeneric(asIScriptGeneric * gen) {
  783. wstring * a = static_cast<wstring *>(gen->GetObject());
  784. unsigned int * b = static_cast<unsigned int *>(gen->GetAddressOfArg(0));
  785. std::wstringstream sstr;
  786. sstr << *a << *b;
  787. std::wstring ret_val = sstr.str();
  788. gen->SetReturnObject(&ret_val);
  789. }
  790.  
  791. static void AddString2BoolGeneric(asIScriptGeneric * gen) {
  792. wstring * a = static_cast<wstring *>(gen->GetObject());
  793. bool * b = static_cast<bool *>(gen->GetAddressOfArg(0));
  794. std::wstringstream sstr;
  795. sstr << *a << (*b ? "true" : "false");
  796. std::wstring ret_val = sstr.str();
  797. gen->SetReturnObject(&ret_val);
  798. }
  799.  
  800. static void AddDouble2StringGeneric(asIScriptGeneric * gen) {
  801. double* a = static_cast<double *>(gen->GetAddressOfArg(0));
  802. wstring * b = static_cast<wstring *>(gen->GetObject());
  803. std::wstringstream sstr;
  804. sstr << *a << *b;
  805. std::wstring ret_val = sstr.str();
  806. gen->SetReturnObject(&ret_val);
  807. }
  808.  
  809. static void AddInt2StringGeneric(asIScriptGeneric * gen) {
  810. int* a = static_cast<int *>(gen->GetAddressOfArg(0));
  811. wstring * b = static_cast<wstring *>(gen->GetObject());
  812. std::wstringstream sstr;
  813. sstr << *a << *b;
  814. std::wstring ret_val = sstr.str();
  815. gen->SetReturnObject(&ret_val);
  816. }
  817.  
  818. static void AddUInt2StringGeneric(asIScriptGeneric * gen) {
  819. unsigned int* a = static_cast<unsigned int *>(gen->GetAddressOfArg(0));
  820. wstring * b = static_cast<wstring *>(gen->GetObject());
  821. std::wstringstream sstr;
  822. sstr << *a << *b;
  823. std::wstring ret_val = sstr.str();
  824. gen->SetReturnObject(&ret_val);
  825. }
  826.  
  827. static void AddBool2StringGeneric(asIScriptGeneric * gen) {
  828. bool* a = static_cast<bool *>(gen->GetAddressOfArg(0));
  829. wstring * b = static_cast<wstring *>(gen->GetObject());
  830. std::wstringstream sstr;
  831. sstr << (*a ? "true" : "false") << *b;
  832. std::wstring ret_val = sstr.str();
  833. gen->SetReturnObject(&ret_val);
  834. }
  835.  
  836. static void StringSubString_Generic(asIScriptGeneric *gen)
  837. {
  838. // Get the arguments
  839. wstring *str = (wstring*)gen->GetObject();
  840. asUINT start = *(int*)gen->GetAddressOfArg(0);
  841. int count = *(int*)gen->GetAddressOfArg(1);
  842.  
  843. // Return the substring
  844. new(gen->GetAddressOfReturnLocation()) wstring(StringSubString(start, count, *str));
  845. }
  846.  
  847. void RegisterStdWString_Generic(asIScriptEngine *engine)
  848. {
  849. int r;
  850.  
  851. // Register the string type
  852. r = engine->RegisterObjectType("string", sizeof(wstring), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert( r >= 0 );
  853.  
  854. #if AS_USE_STRINGPOOL == 1
  855. // Register the string factory
  856. r = engine->RegisterStringFactory("const string &", asFUNCTION(StringFactoryGeneric), asCALL_GENERIC); assert( r >= 0 );
  857.  
  858. // Register the cleanup callback for the string pool
  859. engine->SetEngineUserDataCleanupCallback(CleanupEngineStringPool, STRING_POOL);
  860. #else
  861. // Register the string factory
  862. r = engine->RegisterStringFactory("string", asFUNCTION(StringFactoryGeneric), asCALL_GENERIC); assert( r >= 0 );
  863. #endif
  864.  
  865. // Register the object operator overloads
  866. r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructStringGeneric), asCALL_GENERIC); assert( r >= 0 );
  867. r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f(const string &in)", asFUNCTION(CopyConstructStringGeneric), asCALL_GENERIC); assert( r >= 0 );
  868. r = engine->RegisterObjectBehaviour("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructStringGeneric), asCALL_GENERIC); assert( r >= 0 );
  869. r = engine->RegisterObjectMethod("string", "string &opAssign(const string &in)", asFUNCTION(AssignStringGeneric), asCALL_GENERIC); assert( r >= 0 );
  870. r = engine->RegisterObjectMethod("string", "string &opAddAssign(const string &in)", asFUNCTION(AddAssignStringGeneric), asCALL_GENERIC); assert( r >= 0 );
  871.  
  872. r = engine->RegisterObjectMethod("string", "bool opEquals(const string &in) const", asFUNCTION(StringEqualsGeneric), asCALL_GENERIC); assert( r >= 0 );
  873. r = engine->RegisterObjectMethod("string", "int opCmp(const string &in) const", asFUNCTION(StringCmpGeneric), asCALL_GENERIC); assert( r >= 0 );
  874. r = engine->RegisterObjectMethod("string", "string opAdd(const string &in) const", asFUNCTION(StringAddGeneric), asCALL_GENERIC); assert( r >= 0 );
  875.  
  876. // Register the object methods
  877. r = engine->RegisterObjectMethod("string", "uint length() const", asFUNCTION(StringLengthGeneric), asCALL_GENERIC); assert( r >= 0 );
  878. r = engine->RegisterObjectMethod("string", "void resize(uint)", asFUNCTION(StringResizeGeneric), asCALL_GENERIC); assert( r >= 0 );
  879.  
  880. // Register the index operator, both as a mutator and as an inspector
  881. r = engine->RegisterObjectMethod("string", "uint8 &opIndex(uint)", asFUNCTION(StringCharAtGeneric), asCALL_GENERIC); assert( r >= 0 );
  882. r = engine->RegisterObjectMethod("string", "const uint8 &opIndex(uint) const", asFUNCTION(StringCharAtGeneric), asCALL_GENERIC); assert( r >= 0 );
  883.  
  884. // Automatic conversion from values
  885. r = engine->RegisterObjectMethod("string", "string &opAssign(double)", asFUNCTION(AssignDouble2StringGeneric), asCALL_GENERIC); assert( r >= 0 );
  886. r = engine->RegisterObjectMethod("string", "string &opAddAssign(double)", asFUNCTION(AddAssignDouble2StringGeneric), asCALL_GENERIC); assert( r >= 0 );
  887. r = engine->RegisterObjectMethod("string", "string opAdd(double) const", asFUNCTION(AddString2DoubleGeneric), asCALL_GENERIC); assert( r >= 0 );
  888. r = engine->RegisterObjectMethod("string", "string opAdd_r(double) const", asFUNCTION(AddDouble2StringGeneric), asCALL_GENERIC); assert( r >= 0 );
  889.  
  890. r = engine->RegisterObjectMethod("string", "string &opAssign(int)", asFUNCTION(AssignInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 );
  891. r = engine->RegisterObjectMethod("string", "string &opAddAssign(int)", asFUNCTION(AddAssignInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 );
  892. r = engine->RegisterObjectMethod("string", "string opAdd(int) const", asFUNCTION(AddString2IntGeneric), asCALL_GENERIC); assert( r >= 0 );
  893. r = engine->RegisterObjectMethod("string", "string opAdd_r(int) const", asFUNCTION(AddInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 );
  894.  
  895. r = engine->RegisterObjectMethod("string", "string &opAssign(uint)", asFUNCTION(AssignUInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 );
  896. r = engine->RegisterObjectMethod("string", "string &opAddAssign(uint)", asFUNCTION(AddAssignUInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 );
  897. r = engine->RegisterObjectMethod("string", "string opAdd(uint) const", asFUNCTION(AddString2UIntGeneric), asCALL_GENERIC); assert( r >= 0 );
  898. r = engine->RegisterObjectMethod("string", "string opAdd_r(uint) const", asFUNCTION(AddUInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 );
  899.  
  900. r = engine->RegisterObjectMethod("string", "string &opAssign(bool)", asFUNCTION(AssignBool2StringGeneric), asCALL_GENERIC); assert( r >= 0 );
  901. r = engine->RegisterObjectMethod("string", "string &opAddAssign(bool)", asFUNCTION(AddAssignBool2StringGeneric), asCALL_GENERIC); assert( r >= 0 );
  902. r = engine->RegisterObjectMethod("string", "string opAdd(bool) const", asFUNCTION(AddString2BoolGeneric), asCALL_GENERIC); assert( r >= 0 );
  903. r = engine->RegisterObjectMethod("string", "string opAdd_r(bool) const", asFUNCTION(AddBool2StringGeneric), asCALL_GENERIC); assert( r >= 0 );
  904.  
  905. r = engine->RegisterObjectMethod("string", "string substr(uint start = 0, int count = -1) const", asFUNCTION(StringSubString_Generic), asCALL_GENERIC); assert( r >= 0 );
  906. }
  907.  
  908. void RegisterStdWString(asIScriptEngine * engine)
  909. {
  910. if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY"))
  911. RegisterStdWString_Generic(engine);
  912. else
  913. RegisterStdWString_Native(engine);
  914. }
  915.  
  916. END_AS_NAMESPACE
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement