PageRenderTime 62ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/source/core/XSRuntime.c

http://github.com/macmade/XSFoundation
C | 518 lines | 332 code | 113 blank | 73 comment | 90 complexity | 4535ed52357b165eb23b86e07a3895c1 MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright (c) 2011, Jean-David Gadina <macmade@eosgarden.com>
  3. * Distributed under the Boost Software License, Version 1.0.
  4. *
  5. * Boost Software License - Version 1.0 - August 17th, 2003
  6. *
  7. * Permission is hereby granted, free of charge, to any person or organization
  8. * obtaining a copy of the software and accompanying documentation covered by
  9. * this license (the "Software") to use, reproduce, display, distribute,
  10. * execute, and transmit the Software, and to prepare derivative works of the
  11. * Software, and to permit third-parties to whom the Software is furnished to
  12. * do so, all subject to the following:
  13. *
  14. * The copyright notices in the Software and this entire statement, including
  15. * the above license grant, this restriction and the following disclaimer,
  16. * must be included in all copies of the Software, in whole or in part, and
  17. * all derivative works of the Software, unless such copies or derivative
  18. * works are solely in the form of machine-executable object code generated by
  19. * a source language processor.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
  24. * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
  25. * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
  26. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  27. * DEALINGS IN THE SOFTWARE.
  28. ******************************************************************************/
  29. /* $Id$ */
  30. /*!
  31. * @file XSRuntime.c
  32. * @brief Implementation of the runtime functions
  33. * @author Jean-David Gadina <macmade@eosgarden.com>
  34. * @author St?Šphane Cherpit <stef@eosgarden.com>
  35. */
  36. #include "XS.h"
  37. #include "core/__private/__XSRuntime.h"
  38. #include "core/__private/__XSMemory.h"
  39. #include "core/__private/__XSMemoryDebug.h"
  40. #include "eos-skl/eos-skl.h"
  41. /*!
  42. * define __XS_RUNTIME_CLASS_TABLE_SIZE
  43. * @brief Default allocation size for the runtime class table
  44. */
  45. #define __XS_RUNTIME_CLASS_TABLE_SIZE 1024
  46. /*!
  47. * define __XS___XS_RUNTIME_INIT_CHECK_INIT_CHECK
  48. * @brief Checks if the runtime has been initialized
  49. * @details This macro will produce a fatal error if the runtime has not been initialized.
  50. */
  51. #define __XS___XS_RUNTIME_INIT_CHECK_INIT_CHECK if( __xsruntime_inited == NO ) { XSFatalError( "Error: the runtime has not been initialized\n" ) }
  52. /*!
  53. * @var __xsruntime_inited
  54. * @brief Whether the XSFoundation runtime has been initialized
  55. */
  56. extern BOOL __xsruntime_inited;
  57. /*!
  58. * @var __class_table
  59. * @brief The runtime class table
  60. */
  61. extern XSRuntimeClass * __xsruntime_class_table;
  62. /*!
  63. * @var __class_size
  64. * @brief The allocated size of the runtime class table
  65. */
  66. extern size_t __xsruntime_class_size;
  67. #ifdef _WIN32
  68. extern __declspec( thread ) XSObject __xsruntime_current_object;
  69. extern __declspec( thread ) XSMethod * __xsruntime_caller;
  70. extern __declspec( thread ) XSMethod * __xsruntime_previous_caller;
  71. #elif ( defined __MACH__ )
  72. extern pthread_key_t __xsruntime_current_object;
  73. extern pthread_key_t __xsruntime_caller;
  74. extern pthread_key_t __xsruntime_previous_caller;
  75. #else
  76. extern __thread XSObject __xsruntime_current_object;
  77. extern __thread XSMethod * __xsruntime_caller;
  78. extern __thread XSMethod * __xsruntime_previous_caller;
  79. #endif
  80. /*!
  81. * @var __class_count
  82. * @brief The number of registered classes in the runtime class table
  83. */
  84. extern size_t __xsruntime_class_count;
  85. XSClassID XSRuntime_RegisterClass( const XSClassInfos * const cls )
  86. {
  87. __XS___XS_RUNTIME_INIT_CHECK_INIT_CHECK
  88. if( __xsruntime_class_size == 0 )
  89. {
  90. XSDebugLog( XSDebugLogLevelDebug, "Allocating space for the class table" );
  91. if( NULL == ( __xsruntime_class_table = ( XSRuntimeClass * )calloc( sizeof( XSRuntimeClass ), __XS_RUNTIME_CLASS_TABLE_SIZE ) ) )
  92. {
  93. fprintf( stderr, "Error: unable to allocate the runtime class table!\n" );
  94. exit( EXIT_FAILURE );
  95. }
  96. __xsruntime_class_size += __XS_RUNTIME_CLASS_TABLE_SIZE;
  97. }
  98. if( __xsruntime_class_count == __xsruntime_class_size )
  99. {
  100. XSDebugLog( XSDebugLogLevelDebug, "Reallocating space for the class table" );
  101. if( NULL == ( __xsruntime_class_table = ( XSRuntimeClass * )realloc( __xsruntime_class_table, sizeof( XSRuntimeClass ) * ( __XS_RUNTIME_CLASS_TABLE_SIZE + __xsruntime_class_size ) ) ) )
  102. {
  103. fprintf( stderr, "Error: unable to re-allocate the runtime class table!\n" );
  104. exit( EXIT_FAILURE );
  105. }
  106. __xsruntime_class_size += __XS_RUNTIME_CLASS_TABLE_SIZE;
  107. }
  108. XSDebugLog( XSDebugLogLevelDebug, "Registering class: %s", cls->className );
  109. __xsruntime_class_table[ __xsruntime_class_count ].classInfos = ( XSClassInfos * )cls;
  110. return ++__xsruntime_class_count;
  111. }
  112. void XSRuntime_BindMethodToClassID( XSClassID classID, void ( * func )( XSObject __self, ... ), const char * name, XSModifier modifiers, void ( * casterInit )( XSObject _self ) )
  113. {
  114. XSRuntimeClass * cls;
  115. XSMethod * method;
  116. if( classID > __xsruntime_class_count )
  117. {
  118. return;
  119. }
  120. cls = &( __xsruntime_class_table[ classID - 1 ] );
  121. if( cls->methodCount == cls->methodSize )
  122. {
  123. if( NULL == ( cls->methods = realloc( cls->methods, sizeof( XSMethod ) * ( cls->methodCount + 100 ) ) ) )
  124. {
  125. fprintf( stderr, "Error: unable to re-allocate the class methods table!\n" );
  126. exit( EXIT_FAILURE );
  127. }
  128. }
  129. method = &( cls->methods[ cls->methodCount++ ] );
  130. method->name = ( char * )name;
  131. method->modifiers = modifiers;
  132. method->func = func;
  133. method->casterInit = casterInit;
  134. method->ownerClass = cls;
  135. }
  136. XSMethod * XSRuntime_GetMethod( XSObject object, const char * name )
  137. {
  138. XSClass cls;
  139. if( object == NULL )
  140. {
  141. return NULL;
  142. }
  143. cls = XSRuntime_GetClassForObject( object );
  144. if( cls == NULL )
  145. {
  146. return NULL;
  147. }
  148. __XSRuntime_SetCurrentObject( object );
  149. return __XSRuntime_FindMethod( cls, ( char * )name );
  150. }
  151. XSObject XSRuntime_GetCurrentObject( void )
  152. {
  153. #ifdef __MACH__
  154. return pthread_getspecific( __xsruntime_current_object );
  155. #else
  156. return __xsruntime_current_object;
  157. #endif
  158. }
  159. XSMethod * XSRuntime_GetCaller( void )
  160. {
  161. #ifdef __MACH__
  162. return pthread_getspecific( __xsruntime_caller );
  163. #else
  164. return __xsruntime_caller;
  165. #endif
  166. }
  167. XSMethod * XSRuntime_GetPreviousCaller( void )
  168. {
  169. #ifdef __MACH__
  170. return pthread_getspecific( __xsruntime_previous_caller );
  171. #else
  172. return __xsruntime_previous_caller;
  173. #endif
  174. }
  175. XSObject XSRuntime_CreateInstance( XSClassID typeID )
  176. {
  177. XSRuntimeClass * cls;
  178. size_t size;
  179. XSInstance o;
  180. //size_t i;
  181. __XS___XS_RUNTIME_INIT_CHECK_INIT_CHECK
  182. if( typeID > __xsruntime_class_count || typeID == 0 )
  183. {
  184. return NULL;
  185. }
  186. cls = &( __xsruntime_class_table[ typeID - 1 ] );
  187. size = cls->classInfos->instanceSize;
  188. o = XSAllocInstance( size, typeID );
  189. if( o != NULL )
  190. {
  191. o->__class = cls;
  192. /*for( i = 0; i < cls->methodCount; i++ )
  193. {
  194. if( cls->methods[ i ].casterInit != NULL )
  195. {
  196. cls->methods[ i ].casterInit( o );
  197. }
  198. }*/
  199. }
  200. return ( XSObject )o;
  201. }
  202. XSObject XSRuntime_CreateInstanceOfClass( XSClass cls )
  203. {
  204. XSClassID classID;
  205. if( cls == NULL )
  206. {
  207. return NULL;
  208. }
  209. classID = XSRuntime_GetClassIDForClass( ( XSClass )cls );
  210. if( classID == 0 )
  211. {
  212. return NULL;
  213. }
  214. return XSRuntime_CreateInstance( classID );
  215. }
  216. XSObject XSRuntime_CreateInstanceOfClassWithName( const char * name )
  217. {
  218. size_t i;
  219. XSRuntimeClass * cls;
  220. if( name == NULL )
  221. {
  222. return NULL;
  223. }
  224. for( i = 0; i < __xsruntime_class_count; i++ )
  225. {
  226. cls = &( __xsruntime_class_table[ i ] );
  227. if( strcmp( cls->classInfos->className, name ) == 0 )
  228. {
  229. return XSRuntime_CreateInstance( i + 1 );
  230. }
  231. }
  232. return NULL;
  233. }
  234. const char * XSRuntime_ObjectDescription( void * ptr )
  235. {
  236. XSString description;
  237. XSString str;
  238. __XSMemoryObject * o;
  239. XSClass cls;
  240. if( ptr == NULL )
  241. {
  242. return "<XSObject: nil>";
  243. }
  244. if( XSRuntime_IsInstance( ptr ) == NO )
  245. {
  246. return "<XSNotAnObject>";
  247. }
  248. o = __XSMemory_GetMemoryObject( ptr );
  249. cls = XSRuntime_GetClassForClassID( o->classID );
  250. //str = XSNew( XSString );
  251. //XSAutorelease( XSCall( str, Init ) );
  252. str = XSAutorelease( XSCall( XSString, XSNew( XSString ), Init ) );
  253. //XSApply( str, AppendFormat, ( char * )"<%s: %p>", cls->classInfos->className, ptr );
  254. XSApply( void, str, AppendFormat, ( char * )"<%s: %p>", cls->classInfos->className, ptr );
  255. if( cls->classInfos->toString != NULL )
  256. {
  257. description = cls->classInfos->toString( ptr );
  258. //XSApply( str, AppendFormat, ( char * )" [ %s ]", XSCall( description, CString ) );
  259. XSApply( void, str, AppendFormat, ( char * )" [ %s ]", XSCall( char *, description, CString ) );
  260. }
  261. //return XSCall( str, CString );
  262. return XSCall( char *, str, CString );
  263. }
  264. BOOL XSRuntime_IsInstance( void * ptr )
  265. {
  266. __XSMemoryObject * o;
  267. if( ptr == NULL )
  268. {
  269. return NO;
  270. }
  271. o = __XSMemory_GetMemoryObject( ptr );
  272. if( o->classID > 0 && XSRuntime_GetClassForClassID( o->classID ) != NULL )
  273. {
  274. return YES;
  275. }
  276. return NO;
  277. }
  278. XSClass XSRuntime_GetClassForClassID( XSClassID classID )
  279. {
  280. if( classID == 0 )
  281. {
  282. return NULL;
  283. }
  284. if( classID > __xsruntime_class_count )
  285. {
  286. return NULL;
  287. }
  288. return ( XSClass )&( __xsruntime_class_table[ classID - 1 ] );
  289. }
  290. XSClassID XSRuntime_GetClassIDForClass( XSClass cls )
  291. {
  292. XSUInteger i;
  293. if( cls == NULL )
  294. {
  295. return 0;
  296. }
  297. for( i = 0; i < __xsruntime_class_count; i++ )
  298. {
  299. if( &( __xsruntime_class_table[ i ] ) == cls )
  300. {
  301. return i + 1;
  302. }
  303. }
  304. return 0;
  305. }
  306. XSClassID XSRuntime_GetClassIDForClassWithName( const char * name )
  307. {
  308. XSUInteger i;
  309. if( name == NULL )
  310. {
  311. return 0;
  312. }
  313. for( i = 0; i < __xsruntime_class_count; i++ )
  314. {
  315. if( strcmp( __xsruntime_class_table[ i ].classInfos->className, name ) == 0 )
  316. {
  317. return i + 1;
  318. }
  319. }
  320. return 0;
  321. }
  322. XSClass XSRuntime_GetClassForObject( XSObject object )
  323. {
  324. if( object == NULL )
  325. {
  326. return NULL;
  327. }
  328. if( XSRuntime_IsInstance( object ) == NO )
  329. {
  330. return NULL;
  331. }
  332. return ( ( XSInstance )object )->__class;
  333. }
  334. XSClassID XSRuntime_GetTypeIDForObject( XSObject object )
  335. {
  336. if( object == NULL )
  337. {
  338. return 0;
  339. }
  340. if( XSRuntime_IsInstance( object ) == NO )
  341. {
  342. return 0;
  343. }
  344. return XSRuntime_GetClassIDForClass( XSRuntime_GetClassForObject( object ) );
  345. }
  346. const char * XSRuntime_GetClassNameForClassID( XSClassID classID )
  347. {
  348. if( classID == 0 || classID > __xsruntime_class_count )
  349. {
  350. return "N/A";
  351. }
  352. return __xsruntime_class_table[ classID - 1 ].classInfos->className;
  353. }
  354. const char * XSRuntime_GetClassNameForClass( XSClass cls )
  355. {
  356. if( cls == NULL )
  357. {
  358. return NULL;
  359. }
  360. return cls->classInfos->className;
  361. }
  362. const char * XSRuntime_GetClassNameForObject( XSObject object )
  363. {
  364. if( object == NULL )
  365. {
  366. return NULL;
  367. }
  368. if( XSRuntime_IsInstance( object ) == NO )
  369. {
  370. return NULL;
  371. }
  372. return ( ( XSInstance )object )->__class->classInfos->className;
  373. }
  374. BOOL XSRuntime_IsInstanceOfClass( XSObject object, XSClass cls )
  375. {
  376. if( object == NULL || cls == NULL )
  377. {
  378. return NO;
  379. }
  380. if( XSRuntime_IsInstance( object ) == NO )
  381. {
  382. return NO;
  383. }
  384. if( ( ( XSInstance )object )->__class == cls )
  385. {
  386. return YES;
  387. }
  388. return NO;
  389. }
  390. BOOL XSRuntime_IsInstanceOfClassName( XSObject object, const char * name )
  391. {
  392. if( object == NULL || name == NULL )
  393. {
  394. return NO;
  395. }
  396. if( XSRuntime_IsInstance( object ) == NO )
  397. {
  398. return NO;
  399. }
  400. if( strcmp( ( ( XSRuntimeClass * )object )->classInfos->className, name ) == 0 )
  401. {
  402. return YES;
  403. }
  404. return NO;
  405. }