as_generic.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2010 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. //
  24. // as_generic.cpp
  25. //
  26. // This class handles the call to a function registered with asCALL_GENERIC
  27. //
  28. #include "as_generic.h"
  29. #include "as_scriptfunction.h"
  30. #include "as_objecttype.h"
  31. #include "as_scriptengine.h"
  32. BEGIN_AS_NAMESPACE
  33. // TODO: optimize: The access to the arguments should be optimized so that code
  34. // doesn't have to count the position of the argument with every call
  35. // internal
  36. asCGeneric::asCGeneric(asCScriptEngine *engine, asCScriptFunction *sysFunction, void *currentObject, asDWORD *stackPointer)
  37. {
  38. this->engine = engine;
  39. this->sysFunction = sysFunction;
  40. this->currentObject = currentObject;
  41. this->stackPointer = stackPointer;
  42. objectRegister = 0;
  43. returnVal = 0;
  44. }
  45. // internal
  46. asCGeneric::~asCGeneric()
  47. {
  48. }
  49. // interface
  50. asIScriptEngine *asCGeneric::GetEngine() const
  51. {
  52. return (asIScriptEngine*)engine;
  53. }
  54. // interface
  55. int asCGeneric::GetFunctionId() const
  56. {
  57. return sysFunction->id;
  58. }
  59. // interface
  60. asIScriptFunction *asCGeneric::GetFunctionDescriptor() const
  61. {
  62. return sysFunction;
  63. }
  64. // interface
  65. void *asCGeneric::GetFunctionUserData() const
  66. {
  67. return sysFunction->userData;
  68. }
  69. // interface
  70. void *asCGeneric::GetObject()
  71. {
  72. return currentObject;
  73. }
  74. // interface
  75. int asCGeneric::GetObjectTypeId() const
  76. {
  77. asCDataType dt = asCDataType::CreateObject(sysFunction->objectType, false);
  78. return engine->GetTypeIdFromDataType(dt);
  79. }
  80. // interface
  81. int asCGeneric::GetArgCount() const
  82. {
  83. return (int)sysFunction->parameterTypes.GetLength();
  84. }
  85. // interface
  86. asBYTE asCGeneric::GetArgByte(asUINT arg)
  87. {
  88. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  89. return 0;
  90. // Verify that the type is correct
  91. asCDataType *dt = &sysFunction->parameterTypes[arg];
  92. if( dt->IsObject() || dt->IsReference() )
  93. return 0;
  94. if( dt->GetSizeInMemoryBytes() != 1 )
  95. return 0;
  96. // Determine the position of the argument
  97. int offset = 0;
  98. for( asUINT n = 0; n < arg; n++ )
  99. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  100. // Get the value
  101. return *(asBYTE*)&stackPointer[offset];
  102. }
  103. // interface
  104. asWORD asCGeneric::GetArgWord(asUINT arg)
  105. {
  106. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  107. return 0;
  108. // Verify that the type is correct
  109. asCDataType *dt = &sysFunction->parameterTypes[arg];
  110. if( dt->IsObject() || dt->IsReference() )
  111. return 0;
  112. if( dt->GetSizeInMemoryBytes() != 2 )
  113. return 0;
  114. // Determine the position of the argument
  115. int offset = 0;
  116. for( asUINT n = 0; n < arg; n++ )
  117. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  118. // Get the value
  119. return *(asWORD*)&stackPointer[offset];
  120. }
  121. // interface
  122. asDWORD asCGeneric::GetArgDWord(asUINT arg)
  123. {
  124. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  125. return 0;
  126. // Verify that the type is correct
  127. asCDataType *dt = &sysFunction->parameterTypes[arg];
  128. if( dt->IsObject() || dt->IsReference() )
  129. return 0;
  130. if( dt->GetSizeInMemoryBytes() != 4 )
  131. return 0;
  132. // Determine the position of the argument
  133. int offset = 0;
  134. for( asUINT n = 0; n < arg; n++ )
  135. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  136. // Get the value
  137. return *(asDWORD*)&stackPointer[offset];
  138. }
  139. // interface
  140. asQWORD asCGeneric::GetArgQWord(asUINT arg)
  141. {
  142. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  143. return 0;
  144. // Verify that the type is correct
  145. asCDataType *dt = &sysFunction->parameterTypes[arg];
  146. if( dt->IsObject() || dt->IsReference() )
  147. return 0;
  148. if( dt->GetSizeInMemoryBytes() != 8 )
  149. return 0;
  150. // Determine the position of the argument
  151. int offset = 0;
  152. for( asUINT n = 0; n < arg; n++ )
  153. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  154. // Get the value
  155. return *(asQWORD*)(&stackPointer[offset]);
  156. }
  157. // interface
  158. float asCGeneric::GetArgFloat(asUINT arg)
  159. {
  160. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  161. return 0;
  162. // Verify that the type is correct
  163. asCDataType *dt = &sysFunction->parameterTypes[arg];
  164. if( dt->IsObject() || dt->IsReference() )
  165. return 0;
  166. if( dt->GetSizeInMemoryBytes() != 4 )
  167. return 0;
  168. // Determine the position of the argument
  169. int offset = 0;
  170. for( asUINT n = 0; n < arg; n++ )
  171. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  172. // Get the value
  173. return *(float*)(&stackPointer[offset]);
  174. }
  175. // interface
  176. double asCGeneric::GetArgDouble(asUINT arg)
  177. {
  178. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  179. return 0;
  180. // Verify that the type is correct
  181. asCDataType *dt = &sysFunction->parameterTypes[arg];
  182. if( dt->IsObject() || dt->IsReference() )
  183. return 0;
  184. if( dt->GetSizeInMemoryBytes() != 8 )
  185. return 0;
  186. // Determine the position of the argument
  187. int offset = 0;
  188. for( asUINT n = 0; n < arg; n++ )
  189. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  190. // Get the value
  191. return *(double*)(&stackPointer[offset]);
  192. }
  193. // interface
  194. void *asCGeneric::GetArgAddress(asUINT arg)
  195. {
  196. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  197. return 0;
  198. // Verify that the type is correct
  199. asCDataType *dt = &sysFunction->parameterTypes[arg];
  200. if( !dt->IsReference() && !dt->IsObjectHandle() )
  201. return 0;
  202. // Determine the position of the argument
  203. int offset = 0;
  204. for( asUINT n = 0; n < arg; n++ )
  205. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  206. // Get the value
  207. return (void*)*(size_t*)(&stackPointer[offset]);
  208. }
  209. // interface
  210. void *asCGeneric::GetArgObject(asUINT arg)
  211. {
  212. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  213. return 0;
  214. // Verify that the type is correct
  215. asCDataType *dt = &sysFunction->parameterTypes[arg];
  216. if( !dt->IsObject() )
  217. return 0;
  218. // Determine the position of the argument
  219. int offset = 0;
  220. for( asUINT n = 0; n < arg; n++ )
  221. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  222. // Get the value
  223. return *(void**)(&stackPointer[offset]);
  224. }
  225. // interface
  226. void *asCGeneric::GetAddressOfArg(asUINT arg)
  227. {
  228. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  229. return 0;
  230. // Determine the position of the argument
  231. int offset = 0;
  232. for( asUINT n = 0; n < arg; n++ )
  233. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  234. // For object variables it's necessary to dereference the pointer to get the address of the value
  235. if( !sysFunction->parameterTypes[arg].IsReference() &&
  236. sysFunction->parameterTypes[arg].IsObject() &&
  237. !sysFunction->parameterTypes[arg].IsObjectHandle() )
  238. return *(void**)&stackPointer[offset];
  239. // Get the address of the value
  240. return &stackPointer[offset];
  241. }
  242. // interface
  243. int asCGeneric::GetArgTypeId(asUINT arg) const
  244. {
  245. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  246. return 0;
  247. asCDataType *dt = &sysFunction->parameterTypes[arg];
  248. if( dt->GetTokenType() != ttQuestion )
  249. return engine->GetTypeIdFromDataType(*dt);
  250. else
  251. {
  252. int offset = 0;
  253. for( asUINT n = 0; n < arg; n++ )
  254. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  255. // Skip the actual value to get to the type id
  256. offset += AS_PTR_SIZE;
  257. // Get the value
  258. return stackPointer[offset];
  259. }
  260. }
  261. // interface
  262. int asCGeneric::SetReturnByte(asBYTE val)
  263. {
  264. // Verify the type of the return value
  265. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  266. return asINVALID_TYPE;
  267. if( sysFunction->returnType.GetSizeInMemoryBytes() != 1 )
  268. return asINVALID_TYPE;
  269. // Store the value
  270. *(asBYTE*)&returnVal = val;
  271. return 0;
  272. }
  273. // interface
  274. int asCGeneric::SetReturnWord(asWORD val)
  275. {
  276. // Verify the type of the return value
  277. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  278. return asINVALID_TYPE;
  279. if( sysFunction->returnType.GetSizeInMemoryBytes() != 2 )
  280. return asINVALID_TYPE;
  281. // Store the value
  282. *(asWORD*)&returnVal = val;
  283. return 0;
  284. }
  285. // interface
  286. int asCGeneric::SetReturnDWord(asDWORD val)
  287. {
  288. // Verify the type of the return value
  289. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  290. return asINVALID_TYPE;
  291. if( sysFunction->returnType.GetSizeInMemoryBytes() != 4 )
  292. return asINVALID_TYPE;
  293. // Store the value
  294. *(asDWORD*)&returnVal = val;
  295. return 0;
  296. }
  297. // interface
  298. int asCGeneric::SetReturnQWord(asQWORD val)
  299. {
  300. // Verify the type of the return value
  301. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  302. return asINVALID_TYPE;
  303. if( sysFunction->returnType.GetSizeOnStackDWords() != 2 )
  304. return asINVALID_TYPE;
  305. // Store the value
  306. returnVal = val;
  307. return 0;
  308. }
  309. // interface
  310. int asCGeneric::SetReturnFloat(float val)
  311. {
  312. // Verify the type of the return value
  313. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  314. return asINVALID_TYPE;
  315. if( sysFunction->returnType.GetSizeOnStackDWords() != 1 )
  316. return asINVALID_TYPE;
  317. // Store the value
  318. *(float*)&returnVal = val;
  319. return 0;
  320. }
  321. // interface
  322. int asCGeneric::SetReturnDouble(double val)
  323. {
  324. // Verify the type of the return value
  325. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  326. return asINVALID_TYPE;
  327. if( sysFunction->returnType.GetSizeOnStackDWords() != 2 )
  328. return asINVALID_TYPE;
  329. // Store the value
  330. *(double*)&returnVal = val;
  331. return 0;
  332. }
  333. // interface
  334. int asCGeneric::SetReturnAddress(void *val)
  335. {
  336. // Verify the type of the return value
  337. if( sysFunction->returnType.IsReference() )
  338. {
  339. // Store the value
  340. *(void**)&returnVal = val;
  341. return 0;
  342. }
  343. else if( sysFunction->returnType.IsObjectHandle() )
  344. {
  345. // Store the handle without increasing reference
  346. objectRegister = val;
  347. return 0;
  348. }
  349. return asINVALID_TYPE;
  350. }
  351. // interface
  352. int asCGeneric::SetReturnObject(void *obj)
  353. {
  354. asCDataType *dt = &sysFunction->returnType;
  355. if( !dt->IsObject() )
  356. return asINVALID_TYPE;
  357. if( dt->IsReference() )
  358. {
  359. *(void**)&returnVal = obj;
  360. return 0;
  361. }
  362. if( dt->IsObjectHandle() )
  363. {
  364. // Increase the reference counter
  365. asSTypeBehaviour *beh = &dt->GetObjectType()->beh;
  366. if( obj && beh->addref )
  367. engine->CallObjectMethod(obj, beh->addref);
  368. }
  369. else
  370. {
  371. obj = engine->CreateScriptObjectCopy(obj, engine->GetTypeIdFromDataType(*dt));
  372. }
  373. objectRegister = obj;
  374. return 0;
  375. }
  376. // internal
  377. void *asCGeneric::GetReturnPointer()
  378. {
  379. asCDataType &dt = sysFunction->returnType;
  380. if( dt.IsObject() && !dt.IsReference() )
  381. return &objectRegister;
  382. return &returnVal;
  383. }
  384. // interface
  385. void *asCGeneric::GetAddressOfReturnLocation()
  386. {
  387. asCDataType &dt = sysFunction->returnType;
  388. if( dt.IsObject() && !dt.IsReference() )
  389. {
  390. if( dt.GetObjectType()->flags & asOBJ_VALUE )
  391. {
  392. // Allocate the necessary memory for this object,
  393. // but do not initialize it, as the caller will do that.
  394. objectRegister = engine->CallAlloc(dt.GetObjectType());
  395. // TODO: How will we know if the initialization was successful?
  396. return objectRegister;
  397. }
  398. // Reference types store the handle in the objectReference
  399. return &objectRegister;
  400. }
  401. // Primitive types and references are stored in the returnVal property
  402. return &returnVal;
  403. }
  404. // interface
  405. int asCGeneric::GetReturnTypeId() const
  406. {
  407. return sysFunction->GetReturnTypeId();
  408. }
  409. END_AS_NAMESPACE