stringStack.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include <stdio.h>
  23. #include "console/consoleInternal.h"
  24. #include "console/stringStack.h"
  25. StringStack::StringStack()
  26. {
  27. mBufferSize = 0;
  28. mBuffer = NULL;
  29. mArgBufferSize = 0;
  30. mArgBuffer = NULL;
  31. mNumFrames = 0;
  32. mStart = 0;
  33. mLen = 0;
  34. mStartStackSize = 0;
  35. mFunctionOffset = 0;
  36. validateBufferSize(8192);
  37. validateArgBufferSize(2048);
  38. dMemset(mBuffer, '\0', mBufferSize);
  39. dMemset(mArgBuffer, '\0', mArgBufferSize);
  40. }
  41. StringStack::~StringStack()
  42. {
  43. if( mBuffer )
  44. dFree( mBuffer );
  45. if( mArgBuffer )
  46. dFree( mArgBuffer );
  47. }
  48. void StringStack::validateBufferSize(U32 size)
  49. {
  50. if(size > mBufferSize)
  51. {
  52. mBufferSize = size + 2048;
  53. mBuffer = (char *) dRealloc(mBuffer, mBufferSize);
  54. }
  55. }
  56. void StringStack::validateArgBufferSize(U32 size)
  57. {
  58. if(size > mArgBufferSize)
  59. {
  60. mArgBufferSize = size + 2048;
  61. mArgBuffer = (char *) dRealloc(mArgBuffer, mArgBufferSize);
  62. }
  63. }
  64. void StringStack::setIntValue(U32 i)
  65. {
  66. validateBufferSize(mStart + 32);
  67. dSprintf(mBuffer + mStart, 32, "%d", i);
  68. mLen = dStrlen(mBuffer + mStart);
  69. }
  70. void StringStack::setFloatValue(F64 v)
  71. {
  72. validateBufferSize(mStart + 32);
  73. dSprintf(mBuffer + mStart, 32, "%g", v);
  74. mLen = dStrlen(mBuffer + mStart);
  75. }
  76. char *StringStack::getReturnBuffer(U32 size)
  77. {
  78. if(size > ReturnBufferSpace)
  79. {
  80. AssertFatal(Con::isMainThread(), "Manipulating return buffer from a secondary thread!");
  81. validateArgBufferSize(size);
  82. return mArgBuffer;
  83. }
  84. else
  85. {
  86. validateBufferSize(mStart + size);
  87. return mBuffer + mStart;
  88. }
  89. }
  90. char *StringStack::getArgBuffer(U32 size)
  91. {
  92. AssertFatal(Con::isMainThread(), "Manipulating console arg buffer from a secondary thread!");
  93. validateBufferSize(mStart + mFunctionOffset + size);
  94. char *ret = mBuffer + mStart + mFunctionOffset;
  95. mFunctionOffset += size;
  96. return ret;
  97. }
  98. void StringStack::clearFunctionOffset()
  99. {
  100. //Con::printf("StringStack mFunctionOffset = 0 (from %i)", mFunctionOffset);
  101. mFunctionOffset = 0;
  102. }
  103. void StringStack::setStringValue(const char *s)
  104. {
  105. if(!s)
  106. {
  107. mLen = 0;
  108. mBuffer[mStart] = 0;
  109. return;
  110. }
  111. mLen = dStrlen(s);
  112. validateBufferSize(mStart + mLen + 2);
  113. dStrcpy(mBuffer + mStart, s, mBufferSize - mStart);
  114. }
  115. void StringStack::advance()
  116. {
  117. mStartOffsets[mStartStackSize++] = mStart;
  118. mStart += mLen;
  119. mLen = 0;
  120. }
  121. void StringStack::advanceChar(char c)
  122. {
  123. mStartOffsets[mStartStackSize++] = mStart;
  124. mStart += mLen;
  125. mBuffer[mStart] = c;
  126. mBuffer[mStart+1] = 0;
  127. mStart += 1;
  128. mLen = 0;
  129. }
  130. void StringStack::push()
  131. {
  132. advanceChar(0);
  133. }
  134. void StringStack::rewind()
  135. {
  136. mStart = mStartOffsets[--mStartStackSize];
  137. mLen = dStrlen(mBuffer + mStart);
  138. }
  139. void StringStack::rewindTerminate()
  140. {
  141. mBuffer[mStart] = 0;
  142. mStart = mStartOffsets[--mStartStackSize];
  143. mLen = dStrlen(mBuffer + mStart);
  144. }
  145. U32 StringStack::compare()
  146. {
  147. // Figure out the 1st and 2nd item offsets.
  148. U32 oldStart = mStart;
  149. mStart = mStartOffsets[--mStartStackSize];
  150. // Compare current and previous strings.
  151. U32 ret = !dStricmp(mBuffer + mStart, mBuffer + oldStart);
  152. // Put an empty string on the top of the stack.
  153. mLen = 0;
  154. mBuffer[mStart] = 0;
  155. return ret;
  156. }
  157. void StringStack::pushFrame()
  158. {
  159. //Con::printf("StringStack pushFrame [frame=%i, start=%i]", mNumFrames, mStartStackSize);
  160. mFrameOffsets[mNumFrames++] = mStartStackSize;
  161. mStartOffsets[mStartStackSize++] = mStart;
  162. mStart += ReturnBufferSpace;
  163. validateBufferSize(0);
  164. }
  165. void StringStack::popFrame()
  166. {
  167. //Con::printf("StringStack popFrame [frame=%i, start=%i]", mNumFrames, mStartStackSize);
  168. mStartStackSize = mFrameOffsets[--mNumFrames];
  169. mStart = mStartOffsets[mStartStackSize];
  170. mLen = 0;
  171. }
  172. void StringStack::clearFrames()
  173. {
  174. //Con::printf("StringStack clearFrames");
  175. mNumFrames = 0;
  176. mStart = 0;
  177. mLen = 0;
  178. mStartStackSize = 0;
  179. mFunctionOffset = 0;
  180. }
  181. void ConsoleValueStack::getArgcArgv(StringTableEntry name, U32 *argc, ConsoleValueRef **in_argv, bool popStackFrame /* = false */)
  182. {
  183. U32 startStack = mStackFrames[mFrame-1];
  184. U32 argCount = getMin(mStackPos - startStack, (U32)MaxArgs - 1);
  185. *in_argv = mArgv;
  186. mArgv[0].value = CSTK.pushStackString(name);
  187. for(U32 i = 0; i < argCount; i++) {
  188. ConsoleValueRef *ref = &mArgv[i+1];
  189. ref->value = &mStack[startStack + i];
  190. }
  191. argCount++;
  192. *argc = argCount;
  193. if(popStackFrame)
  194. popFrame();
  195. }
  196. ConsoleValueStack::ConsoleValueStack() :
  197. mFrame(0),
  198. mStackPos(0)
  199. {
  200. for (int i=0; i<ConsoleValueStack::MaxStackDepth; i++) {
  201. mStack[i].init();
  202. mStack[i].type = ConsoleValue::TypeInternalString;
  203. }
  204. }
  205. ConsoleValueStack::~ConsoleValueStack()
  206. {
  207. }
  208. void ConsoleValueStack::pushVar(ConsoleValue *variable)
  209. {
  210. if (mStackPos == ConsoleValueStack::MaxStackDepth) {
  211. AssertFatal(false, "Console Value Stack is empty");
  212. return;
  213. }
  214. switch (variable->type)
  215. {
  216. case ConsoleValue::TypeInternalInt:
  217. mStack[mStackPos++].setIntValue((S32)variable->getIntValue());
  218. case ConsoleValue::TypeInternalFloat:
  219. mStack[mStackPos++].setFloatValue((F32)variable->getFloatValue());
  220. default:
  221. mStack[mStackPos++].setStackStringValue(variable->getStringValue());
  222. }
  223. }
  224. void ConsoleValueStack::pushValue(ConsoleValue &variable)
  225. {
  226. if (mStackPos == ConsoleValueStack::MaxStackDepth) {
  227. AssertFatal(false, "Console Value Stack is empty");
  228. return;
  229. }
  230. switch (variable.type)
  231. {
  232. case ConsoleValue::TypeInternalInt:
  233. mStack[mStackPos++].setIntValue((S32)variable.getIntValue());
  234. case ConsoleValue::TypeInternalFloat:
  235. mStack[mStackPos++].setFloatValue((F32)variable.getFloatValue());
  236. case ConsoleValue::TypeInternalStringStackPtr:
  237. mStack[mStackPos++].setStringStackPtrValue(variable.getStringStackPtr());
  238. default:
  239. mStack[mStackPos++].setStringValue(variable.getStringValue());
  240. }
  241. }
  242. ConsoleValue* ConsoleValueStack::reserveValues(U32 count)
  243. {
  244. U32 startPos = mStackPos;
  245. if (startPos+count >= ConsoleValueStack::MaxStackDepth) {
  246. AssertFatal(false, "Console Value Stack is empty");
  247. return NULL;
  248. }
  249. //Con::printf("[%i]CSTK reserveValues %i", mStackPos, count);
  250. mStackPos += count;
  251. return &mStack[startPos];
  252. }
  253. bool ConsoleValueStack::reserveValues(U32 count, ConsoleValueRef *outValues)
  254. {
  255. U32 startPos = mStackPos;
  256. if (startPos+count >= ConsoleValueStack::MaxStackDepth) {
  257. AssertFatal(false, "Console Value Stack is empty");
  258. return false;
  259. }
  260. //Con::printf("[%i]CSTK reserveValues %i", mStackPos, count);
  261. for (U32 i=0; i<count; i++)
  262. {
  263. outValues[i].value = &mStack[mStackPos+i];
  264. }
  265. mStackPos += count;
  266. return true;
  267. }
  268. ConsoleValue *ConsoleValueStack::pushString(const char *value)
  269. {
  270. if (mStackPos == ConsoleValueStack::MaxStackDepth) {
  271. AssertFatal(false, "Console Value Stack is empty");
  272. return NULL;
  273. }
  274. //Con::printf("[%i]CSTK pushString %s", mStackPos, value);
  275. mStack[mStackPos++].setStringValue(value);
  276. return &mStack[mStackPos-1];
  277. }
  278. ConsoleValue *ConsoleValueStack::pushStackString(const char *value)
  279. {
  280. if (mStackPos == ConsoleValueStack::MaxStackDepth) {
  281. AssertFatal(false, "Console Value Stack is empty");
  282. return NULL;
  283. }
  284. //Con::printf("[%i]CSTK pushString %s", mStackPos, value);
  285. mStack[mStackPos++].setStackStringValue(value);
  286. return &mStack[mStackPos-1];
  287. }
  288. ConsoleValue *ConsoleValueStack::pushStringStackPtr(StringStackPtr value)
  289. {
  290. if (mStackPos == ConsoleValueStack::MaxStackDepth) {
  291. AssertFatal(false, "Console Value Stack is empty");
  292. return NULL;
  293. }
  294. //Con::printf("[%i]CSTK pushStringStackPtr %s", mStackPos, StringStackPtrRef(value).getPtr(&STR));
  295. mStack[mStackPos++].setStringStackPtrValue(value);
  296. return &mStack[mStackPos-1];
  297. }
  298. ConsoleValue *ConsoleValueStack::pushUINT(U32 value)
  299. {
  300. if (mStackPos == ConsoleValueStack::MaxStackDepth) {
  301. AssertFatal(false, "Console Value Stack is empty");
  302. return NULL;
  303. }
  304. //Con::printf("[%i]CSTK pushUINT %i", mStackPos, value);
  305. mStack[mStackPos++].setIntValue(value);
  306. return &mStack[mStackPos-1];
  307. }
  308. ConsoleValue *ConsoleValueStack::pushFLT(float value)
  309. {
  310. if (mStackPos == ConsoleValueStack::MaxStackDepth) {
  311. AssertFatal(false, "Console Value Stack is empty");
  312. return NULL;
  313. }
  314. //Con::printf("[%i]CSTK pushFLT %f", mStackPos, value);
  315. mStack[mStackPos++].setFloatValue(value);
  316. return &mStack[mStackPos-1];
  317. }
  318. static ConsoleValue gNothing;
  319. ConsoleValue* ConsoleValueStack::pop()
  320. {
  321. if (mStackPos == 0) {
  322. AssertFatal(false, "Console Value Stack is empty");
  323. return &gNothing;
  324. }
  325. return &mStack[--mStackPos];
  326. }
  327. void ConsoleValueStack::pushFrame()
  328. {
  329. //Con::printf("CSTK pushFrame[%i] (%i)", mFrame, mStackPos);
  330. mStackFrames[mFrame++] = mStackPos;
  331. }
  332. void ConsoleValueStack::resetFrame()
  333. {
  334. if (mFrame == 0) {
  335. mStackPos = 0;
  336. return;
  337. }
  338. U32 start = mStackFrames[mFrame-1];
  339. //for (U32 i=start; i<mStackPos; i++) {
  340. //mStack[i].clear();
  341. //}
  342. mStackPos = start;
  343. //Con::printf("CSTK resetFrame to %i", mStackPos);
  344. }
  345. void ConsoleValueStack::clearFrames()
  346. {
  347. mStackPos = 0;
  348. mFrame = 0;
  349. }
  350. void ConsoleValueStack::popFrame()
  351. {
  352. //Con::printf("CSTK popFrame");
  353. if (mFrame == 0) {
  354. // Go back to start
  355. mStackPos = 0;
  356. return;
  357. }
  358. U32 start = mStackFrames[mFrame-1];
  359. //for (U32 i=start; i<mStackPos; i++) {
  360. //mStack[i].clear();
  361. //}
  362. mStackPos = start;
  363. mFrame--;
  364. }