Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Aug 11th, 2013  |  syntax: None  |  size: 33.89 KB  |  views: 34  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  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
clone this paste RAW Paste Data