2
0

as_generic.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2011 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. #ifdef AS_DEPRECATED
  60. // deprecated since 2011-10-03
  61. // interface
  62. asIScriptFunction *asCGeneric::GetFunctionDescriptor() const
  63. {
  64. return sysFunction;
  65. }
  66. #endif
  67. // interface
  68. asIScriptFunction *asCGeneric::GetFunction() const
  69. {
  70. return sysFunction;
  71. }
  72. // interface
  73. void *asCGeneric::GetFunctionUserData() const
  74. {
  75. return sysFunction->userData;
  76. }
  77. // interface
  78. void *asCGeneric::GetObject()
  79. {
  80. return currentObject;
  81. }
  82. // interface
  83. int asCGeneric::GetObjectTypeId() const
  84. {
  85. asCDataType dt = asCDataType::CreateObject(sysFunction->objectType, false);
  86. return engine->GetTypeIdFromDataType(dt);
  87. }
  88. // interface
  89. int asCGeneric::GetArgCount() const
  90. {
  91. return (int)sysFunction->parameterTypes.GetLength();
  92. }
  93. // interface
  94. asBYTE asCGeneric::GetArgByte(asUINT arg)
  95. {
  96. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  97. return 0;
  98. // Verify that the type is correct
  99. asCDataType *dt = &sysFunction->parameterTypes[arg];
  100. if( dt->IsObject() || dt->IsReference() )
  101. return 0;
  102. if( dt->GetSizeInMemoryBytes() != 1 )
  103. return 0;
  104. // Determine the position of the argument
  105. int offset = 0;
  106. for( asUINT n = 0; n < arg; n++ )
  107. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  108. // Get the value
  109. return *(asBYTE*)&stackPointer[offset];
  110. }
  111. // interface
  112. asWORD asCGeneric::GetArgWord(asUINT arg)
  113. {
  114. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  115. return 0;
  116. // Verify that the type is correct
  117. asCDataType *dt = &sysFunction->parameterTypes[arg];
  118. if( dt->IsObject() || dt->IsReference() )
  119. return 0;
  120. if( dt->GetSizeInMemoryBytes() != 2 )
  121. return 0;
  122. // Determine the position of the argument
  123. int offset = 0;
  124. for( asUINT n = 0; n < arg; n++ )
  125. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  126. // Get the value
  127. return *(asWORD*)&stackPointer[offset];
  128. }
  129. // interface
  130. asDWORD asCGeneric::GetArgDWord(asUINT arg)
  131. {
  132. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  133. return 0;
  134. // Verify that the type is correct
  135. asCDataType *dt = &sysFunction->parameterTypes[arg];
  136. if( dt->IsObject() || dt->IsReference() )
  137. return 0;
  138. if( dt->GetSizeInMemoryBytes() != 4 )
  139. return 0;
  140. // Determine the position of the argument
  141. int offset = 0;
  142. for( asUINT n = 0; n < arg; n++ )
  143. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  144. // Get the value
  145. return *(asDWORD*)&stackPointer[offset];
  146. }
  147. // interface
  148. asQWORD asCGeneric::GetArgQWord(asUINT arg)
  149. {
  150. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  151. return 0;
  152. // Verify that the type is correct
  153. asCDataType *dt = &sysFunction->parameterTypes[arg];
  154. if( dt->IsObject() || dt->IsReference() )
  155. return 0;
  156. if( dt->GetSizeInMemoryBytes() != 8 )
  157. return 0;
  158. // Determine the position of the argument
  159. int offset = 0;
  160. for( asUINT n = 0; n < arg; n++ )
  161. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  162. // Get the value
  163. return *(asQWORD*)(&stackPointer[offset]);
  164. }
  165. // interface
  166. float asCGeneric::GetArgFloat(asUINT arg)
  167. {
  168. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  169. return 0;
  170. // Verify that the type is correct
  171. asCDataType *dt = &sysFunction->parameterTypes[arg];
  172. if( dt->IsObject() || dt->IsReference() )
  173. return 0;
  174. if( dt->GetSizeInMemoryBytes() != 4 )
  175. return 0;
  176. // Determine the position of the argument
  177. int offset = 0;
  178. for( asUINT n = 0; n < arg; n++ )
  179. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  180. // Get the value
  181. return *(float*)(&stackPointer[offset]);
  182. }
  183. // interface
  184. double asCGeneric::GetArgDouble(asUINT arg)
  185. {
  186. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  187. return 0;
  188. // Verify that the type is correct
  189. asCDataType *dt = &sysFunction->parameterTypes[arg];
  190. if( dt->IsObject() || dt->IsReference() )
  191. return 0;
  192. if( dt->GetSizeInMemoryBytes() != 8 )
  193. return 0;
  194. // Determine the position of the argument
  195. int offset = 0;
  196. for( asUINT n = 0; n < arg; n++ )
  197. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  198. // Get the value
  199. return *(double*)(&stackPointer[offset]);
  200. }
  201. // interface
  202. void *asCGeneric::GetArgAddress(asUINT arg)
  203. {
  204. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  205. return 0;
  206. // Verify that the type is correct
  207. asCDataType *dt = &sysFunction->parameterTypes[arg];
  208. if( !dt->IsReference() && !dt->IsObjectHandle() )
  209. return 0;
  210. // Determine the position of the argument
  211. int offset = 0;
  212. for( asUINT n = 0; n < arg; n++ )
  213. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  214. // Get the value
  215. return (void*)*(size_t*)(&stackPointer[offset]);
  216. }
  217. // interface
  218. void *asCGeneric::GetArgObject(asUINT arg)
  219. {
  220. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  221. return 0;
  222. // Verify that the type is correct
  223. asCDataType *dt = &sysFunction->parameterTypes[arg];
  224. if( !dt->IsObject() )
  225. return 0;
  226. // Determine the position of the argument
  227. int offset = 0;
  228. for( asUINT n = 0; n < arg; n++ )
  229. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  230. // Get the value
  231. return *(void**)(&stackPointer[offset]);
  232. }
  233. // interface
  234. void *asCGeneric::GetAddressOfArg(asUINT arg)
  235. {
  236. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  237. return 0;
  238. // Determine the position of the argument
  239. int offset = 0;
  240. for( asUINT n = 0; n < arg; n++ )
  241. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  242. // For object variables it's necessary to dereference the pointer to get the address of the value
  243. if( !sysFunction->parameterTypes[arg].IsReference() &&
  244. sysFunction->parameterTypes[arg].IsObject() &&
  245. !sysFunction->parameterTypes[arg].IsObjectHandle() )
  246. return *(void**)&stackPointer[offset];
  247. // Get the address of the value
  248. return &stackPointer[offset];
  249. }
  250. // interface
  251. int asCGeneric::GetArgTypeId(asUINT arg) const
  252. {
  253. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  254. return 0;
  255. asCDataType *dt = &sysFunction->parameterTypes[arg];
  256. if( dt->GetTokenType() != ttQuestion )
  257. return engine->GetTypeIdFromDataType(*dt);
  258. else
  259. {
  260. int offset = 0;
  261. for( asUINT n = 0; n < arg; n++ )
  262. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  263. // Skip the actual value to get to the type id
  264. offset += AS_PTR_SIZE;
  265. // Get the value
  266. return stackPointer[offset];
  267. }
  268. }
  269. // interface
  270. int asCGeneric::SetReturnByte(asBYTE val)
  271. {
  272. // Verify the type of the return value
  273. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  274. return asINVALID_TYPE;
  275. if( sysFunction->returnType.GetSizeInMemoryBytes() != 1 )
  276. return asINVALID_TYPE;
  277. // Store the value
  278. *(asBYTE*)&returnVal = val;
  279. return 0;
  280. }
  281. // interface
  282. int asCGeneric::SetReturnWord(asWORD val)
  283. {
  284. // Verify the type of the return value
  285. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  286. return asINVALID_TYPE;
  287. if( sysFunction->returnType.GetSizeInMemoryBytes() != 2 )
  288. return asINVALID_TYPE;
  289. // Store the value
  290. *(asWORD*)&returnVal = val;
  291. return 0;
  292. }
  293. // interface
  294. int asCGeneric::SetReturnDWord(asDWORD val)
  295. {
  296. // Verify the type of the return value
  297. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  298. return asINVALID_TYPE;
  299. if( sysFunction->returnType.GetSizeInMemoryBytes() != 4 )
  300. return asINVALID_TYPE;
  301. // Store the value
  302. *(asDWORD*)&returnVal = val;
  303. return 0;
  304. }
  305. // interface
  306. int asCGeneric::SetReturnQWord(asQWORD val)
  307. {
  308. // Verify the type of the return value
  309. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  310. return asINVALID_TYPE;
  311. if( sysFunction->returnType.GetSizeOnStackDWords() != 2 )
  312. return asINVALID_TYPE;
  313. // Store the value
  314. returnVal = val;
  315. return 0;
  316. }
  317. // interface
  318. int asCGeneric::SetReturnFloat(float val)
  319. {
  320. // Verify the type of the return value
  321. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  322. return asINVALID_TYPE;
  323. if( sysFunction->returnType.GetSizeOnStackDWords() != 1 )
  324. return asINVALID_TYPE;
  325. // Store the value
  326. *(float*)&returnVal = val;
  327. return 0;
  328. }
  329. // interface
  330. int asCGeneric::SetReturnDouble(double val)
  331. {
  332. // Verify the type of the return value
  333. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  334. return asINVALID_TYPE;
  335. if( sysFunction->returnType.GetSizeOnStackDWords() != 2 )
  336. return asINVALID_TYPE;
  337. // Store the value
  338. *(double*)&returnVal = val;
  339. return 0;
  340. }
  341. // interface
  342. int asCGeneric::SetReturnAddress(void *val)
  343. {
  344. // Verify the type of the return value
  345. if( sysFunction->returnType.IsReference() )
  346. {
  347. // Store the value
  348. *(void**)&returnVal = val;
  349. return 0;
  350. }
  351. else if( sysFunction->returnType.IsObjectHandle() )
  352. {
  353. // Store the handle without increasing reference
  354. objectRegister = val;
  355. return 0;
  356. }
  357. return asINVALID_TYPE;
  358. }
  359. // interface
  360. int asCGeneric::SetReturnObject(void *obj)
  361. {
  362. asCDataType *dt = &sysFunction->returnType;
  363. if( !dt->IsObject() )
  364. return asINVALID_TYPE;
  365. if( dt->IsReference() )
  366. {
  367. *(void**)&returnVal = obj;
  368. return 0;
  369. }
  370. if( dt->IsObjectHandle() )
  371. {
  372. // Increase the reference counter
  373. asSTypeBehaviour *beh = &dt->GetObjectType()->beh;
  374. if( obj && beh->addref )
  375. engine->CallObjectMethod(obj, beh->addref);
  376. }
  377. else
  378. {
  379. #ifndef AS_OLD
  380. // If function returns object by value the memory is already allocated.
  381. // Here we should just initialize that memory by calling the copy constructor
  382. // or the default constructor followed by the assignment operator
  383. void *mem = (void*)*(size_t*)&stackPointer[-AS_PTR_SIZE];
  384. engine->ConstructScriptObjectCopy(mem, obj, dt->GetObjectType());
  385. return 0;
  386. #else
  387. obj = engine->CreateScriptObjectCopy(obj, engine->GetTypeIdFromDataType(*dt));
  388. #endif
  389. }
  390. objectRegister = obj;
  391. return 0;
  392. }
  393. // internal
  394. void *asCGeneric::GetReturnPointer()
  395. {
  396. asCDataType &dt = sysFunction->returnType;
  397. if( dt.IsObject() && !dt.IsReference() )
  398. {
  399. // This function doesn't support returning on the stack but the use of
  400. // the function doesn't require it so we don't need to implement it here.
  401. asASSERT( !sysFunction->DoesReturnOnStack() );
  402. return &objectRegister;
  403. }
  404. return &returnVal;
  405. }
  406. // interface
  407. void *asCGeneric::GetAddressOfReturnLocation()
  408. {
  409. asCDataType &dt = sysFunction->returnType;
  410. if( dt.IsObject() && !dt.IsReference() )
  411. {
  412. #ifndef AS_OLD
  413. if( sysFunction->DoesReturnOnStack() )
  414. {
  415. // The memory is already preallocated on the stack,
  416. // and the pointer to the location is found before the first arg
  417. return (void*)*(size_t*)&stackPointer[-AS_PTR_SIZE];
  418. }
  419. #else
  420. if( dt.GetObjectType()->flags & asOBJ_VALUE )
  421. {
  422. // Allocate the necessary memory for this object,
  423. // but do not initialize it, as the caller will do that.
  424. objectRegister = engine->CallAlloc(dt.GetObjectType());
  425. // TODO: How will we know if the initialization was successful?
  426. return objectRegister;
  427. }
  428. #endif
  429. // Reference types store the handle in the objectReference
  430. return &objectRegister;
  431. }
  432. // Primitive types and references are stored in the returnVal property
  433. return &returnVal;
  434. }
  435. // interface
  436. int asCGeneric::GetReturnTypeId() const
  437. {
  438. return sysFunction->GetReturnTypeId();
  439. }
  440. END_AS_NAMESPACE