PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/runtime/base/dynamic_object_data.cpp

https://github.com/zsj888/hiphop-php
C++ | 421 lines | 354 code | 41 blank | 26 comment | 82 complexity | 9ff0145e6b53443eb1f0f449c8e59a94 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010 Facebook, Inc. (http://www.facebook.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. */
  16. #include <runtime/base/dynamic_object_data.h>
  17. #include <runtime/base/complex_types.h>
  18. #include <runtime/base/array/array_init.h>
  19. #include <runtime/base/externals.h>
  20. #include <util/util.h>
  21. namespace HPHP {
  22. /////////////////////////////////////////////////////////////////////////////
  23. // constructor/destructor
  24. DynamicObjectData::DynamicObjectData(const char* pname,
  25. ObjectData* r /* = NULL */) :
  26. root(r ? r : this) {
  27. if (pname) {
  28. CountableHelper h(root);
  29. parent = create_object(pname, Array(), false, root);
  30. }
  31. }
  32. void DynamicObjectData::init() {
  33. if (!parent.isNull()) {
  34. parent->init();
  35. }
  36. }
  37. void DynamicObjectData::dynConstruct(CArrRef params) {
  38. if (!parent.isNull()) {
  39. parent->dynConstruct(params);
  40. }
  41. }
  42. void DynamicObjectData::
  43. dynConstructFromEval(Eval::VariableEnvironment &env,
  44. const Eval::FunctionCallExpression *call) {
  45. if (!parent.isNull()) {
  46. parent->dynConstructFromEval(env, call);
  47. }
  48. }
  49. void DynamicObjectData::destruct() {
  50. if (!parent.isNull()) {
  51. if (inCtorDtor()) {
  52. parent->setInDtor();
  53. }
  54. parent = Object();
  55. }
  56. }
  57. void DynamicObjectData::setRoot(ObjectData *r) {
  58. root = r;
  59. if (!parent.isNull()) {
  60. parent->setRoot(r);
  61. }
  62. }
  63. ObjectData *DynamicObjectData::getRoot() {
  64. return root;
  65. }
  66. ObjectData* DynamicObjectData::clone() {
  67. ObjectData *clone = cloneImpl();
  68. clone->setRoot(clone);
  69. return clone;
  70. }
  71. ///////////////////////////////////////////////////////////////////////////////
  72. // instance methods and properties
  73. bool DynamicObjectData::o_exists(CStrRef propName, int64 hash,
  74. const char *context /* = NULL */) const {
  75. if (!parent.isNull()) {
  76. return parent->o_exists(propName, hash, context);
  77. } else {
  78. return ObjectData::o_exists(propName, hash, context);
  79. }
  80. }
  81. Variant DynamicObjectData::o_get(CStrRef propName, int64 hash,
  82. bool error /* = true */, const char *context /* = NULL */) {
  83. if (!parent.isNull()) {
  84. return parent->o_get(propName, hash, error, context);
  85. } else {
  86. if (propName.size() == 0) {
  87. return null;
  88. }
  89. if (o_properties && o_properties->exists(propName, hash)) {
  90. return o_properties->rvalAt(propName, hash);
  91. }
  92. if (root->getAttribute(InGet)) {
  93. return ObjectData::doGet(propName, error);
  94. } else {
  95. AttributeSetter a(InGet, root);
  96. return root->doGet(propName, error);
  97. }
  98. }
  99. }
  100. void DynamicObjectData::o_get(Array &props) const {
  101. if (!parent.isNull()) {
  102. return parent->o_get(props);
  103. } else {
  104. return ObjectData::o_get(props);
  105. }
  106. }
  107. Variant DynamicObjectData::o_set(CStrRef propName, int64 hash, CVarRef v,
  108. bool forInit /* = false */, const char *context /* = NULL */) {
  109. if (!parent.isNull()) {
  110. return parent->o_set(propName, hash, v, forInit, context);
  111. } else {
  112. if (propName.size() == 0) {
  113. throw EmptyObjectPropertyException();
  114. }
  115. if (o_properties && o_properties->exists(propName, hash)) {
  116. o_properties->set(propName, v, hash);
  117. return v;
  118. }
  119. if (forInit || root->getAttribute(InSet)) {
  120. return ObjectData::t___set(propName, v);
  121. } else {
  122. AttributeSetter a(InSet, root);
  123. return root->t___set(propName, v);
  124. }
  125. }
  126. }
  127. Variant &DynamicObjectData::o_lval(CStrRef propName, int64 hash,
  128. const char *context /* = NULL */) {
  129. if (!parent.isNull()) {
  130. return parent->o_lval(propName, hash, context);
  131. } else {
  132. if (o_properties && o_properties->exists(propName)) {
  133. return o_properties->lvalAt(propName, hash);
  134. }
  135. return root->___lval(propName);
  136. }
  137. }
  138. Array DynamicObjectData::o_toArray() const {
  139. if (!parent.isNull()) {
  140. return parent->o_toArray();
  141. } else {
  142. return ObjectData::o_toArray();
  143. }
  144. }
  145. Array DynamicObjectData::o_getDynamicProperties() const {
  146. if (!parent.isNull()) {
  147. return parent->o_getDynamicProperties();
  148. } else {
  149. return ObjectData::o_getDynamicProperties();
  150. }
  151. }
  152. Variant DynamicObjectData::o_invoke(const char *s, CArrRef params, int64 hash,
  153. bool fatal /* = false */) {
  154. if (!parent.isNull()) {
  155. return parent->o_invoke(s, params, hash, fatal);
  156. } else {
  157. return root->doCall(s, params, fatal);
  158. }
  159. }
  160. Variant DynamicObjectData::o_invoke_ex(const char *clsname, const char *s,
  161. CArrRef params, int64 hash,
  162. bool fatal /* = false */) {
  163. if (strcasecmp(o_getClassName(), clsname) == 0) {
  164. return o_invoke(s, params, hash);
  165. } else if(!parent.isNull()) {
  166. return parent->o_invoke_ex(clsname, s, params, hash, fatal);
  167. } else {
  168. return ObjectData::o_invoke_ex(clsname, s, params, hash, fatal);
  169. }
  170. }
  171. Variant DynamicObjectData::o_invoke_few_args(const char *s, int64 hash, int count,
  172. INVOKE_FEW_ARGS_IMPL_ARGS) {
  173. if (!parent.isNull()) {
  174. return parent->o_invoke_few_args(s, hash, count,
  175. INVOKE_FEW_ARGS_PASS_ARGS);
  176. } else {
  177. switch (count) {
  178. case 0: {
  179. return DynamicObjectData::o_invoke(s, Array(), hash);
  180. }
  181. case 1: {
  182. Array params(ArrayInit(1, true).set(0, a0).create());
  183. return DynamicObjectData::o_invoke(s, params, hash);
  184. }
  185. case 2: {
  186. Array params(ArrayInit(2, true).set(0, a0).set(1, a1).create());
  187. return DynamicObjectData::o_invoke(s, params, hash);
  188. }
  189. case 3: {
  190. Array params(ArrayInit(3, true).set(0, a0).set(1, a1).set(2, a2).
  191. create());
  192. return DynamicObjectData::o_invoke(s, params, hash);
  193. }
  194. #if INVOKE_FEW_ARGS_COUNT > 3
  195. case 4: {
  196. Array params(ArrayInit(4, true).set(0, a0).set(1, a1).set(2, a2).
  197. set(3, a3).create());
  198. return DynamicObjectData::o_invoke(s, params, hash);
  199. }
  200. case 5: {
  201. Array params(ArrayInit(5, true).set(0, a0).set(1, a1).set(2, a2).
  202. set(3, a3).set(4, a4).create());
  203. return DynamicObjectData::o_invoke(s, params, hash);
  204. }
  205. case 6: {
  206. Array params(ArrayInit(6, true).set(0, a0).set(1, a1).set(2, a2).
  207. set(3, a3).set(4, a4).set(5, a5).
  208. create());
  209. return DynamicObjectData::o_invoke(s, params, hash);
  210. }
  211. #endif
  212. #if INVOKE_FEW_ARGS_COUNT > 6
  213. case 7: {
  214. Array params(ArrayInit(7, true).set(0, a0).set(1, a1).set(2, a2).
  215. set(3, a3).set(4, a4).set(5, a5).
  216. set(6, a6).create());
  217. return DynamicObjectData::o_invoke(s, params, hash);
  218. }
  219. case 8: {
  220. Array params(ArrayInit(8, true).set(0, a0).set(1, a1).set(2, a2).
  221. set(3, a3).set(4, a4).set(5, a5).
  222. set(6, a6).set(7, a7).create());
  223. return DynamicObjectData::o_invoke(s, params, hash);
  224. }
  225. case 9: {
  226. Array params(ArrayInit(9, true).set(0, a0).set(1, a1).set(2, a2).
  227. set(3, a3).set(4, a4).set(5, a5).
  228. set(6, a6).set(7, a7).set(8, a8).
  229. create());
  230. return DynamicObjectData::o_invoke(s, params, hash);
  231. }
  232. case 10: {
  233. Array params(ArrayInit(10, true).set(0, a0).set(1, a1).set(2, a2).
  234. set(3, a3).set(4, a4).set(5, a5).
  235. set(6, a6).set(7, a7).set(8, a8).
  236. set(9, a9).create());
  237. return DynamicObjectData::o_invoke(s, params, hash);
  238. }
  239. #endif
  240. default:
  241. ASSERT(false);
  242. }
  243. return null;
  244. }
  245. }
  246. Variant DynamicObjectData::o_root_invoke(const char *s, CArrRef params,
  247. int64 hash, bool fatal /* = false */) {
  248. if (root != this) {
  249. return root->o_root_invoke(s, params, hash, fatal);
  250. } else {
  251. return o_invoke(s, params, hash, fatal);
  252. }
  253. }
  254. Variant
  255. DynamicObjectData::o_root_invoke_few_args(const char *s, int64 hash, int count,
  256. INVOKE_FEW_ARGS_IMPL_ARGS) {
  257. if (root != this) {
  258. return root->o_invoke_few_args(s, hash, count, INVOKE_FEW_ARGS_PASS_ARGS);
  259. } else {
  260. return o_invoke_few_args(s, hash, count, INVOKE_FEW_ARGS_PASS_ARGS);
  261. }
  262. }
  263. Variant DynamicObjectData::doCall(Variant v_name, Variant v_arguments,
  264. bool fatal) {
  265. if (!parent.isNull()) {
  266. return parent->doCall(v_name, v_arguments, fatal);
  267. } else {
  268. return ObjectData::doCall(v_name, v_arguments, fatal);
  269. }
  270. }
  271. Variant DynamicObjectData::doRootCall(Variant v_name, Variant v_arguments,
  272. bool fatal) {
  273. return root->doCall(v_name, v_arguments, fatal);
  274. }
  275. Variant DynamicObjectData::doGet(Variant v_name, bool error) {
  276. if (!parent.isNull()) {
  277. return parent->doGet(v_name, error);
  278. } else {
  279. return ObjectData::doGet(v_name, error);
  280. }
  281. }
  282. ///////////////////////////////////////////////////////////////////////////////
  283. // magic methods that user classes can override, and these are default handlers
  284. // or actions to take:
  285. Variant DynamicObjectData::t___destruct() {
  286. if (!parent.isNull()) {
  287. return parent->t___destruct();
  288. } else {
  289. return ObjectData::t___destruct();
  290. }
  291. }
  292. Variant DynamicObjectData::t___set(Variant v_name, Variant v_value) {
  293. if (v_value.isReferenced()) {
  294. v_value.setContagious();
  295. }
  296. if (!parent.isNull()) {
  297. return parent->t___set(v_name, v_value);
  298. } else {
  299. return ObjectData::t___set(v_name, v_value);
  300. }
  301. }
  302. Variant DynamicObjectData::t___get(Variant v_name) {
  303. if (!parent.isNull()) {
  304. return parent->t___get(v_name);
  305. } else {
  306. return ObjectData::t___get(v_name);
  307. }
  308. }
  309. bool DynamicObjectData::t___isset(Variant v_name) {
  310. if (!parent.isNull()) {
  311. return parent->t___isset(v_name);
  312. } else {
  313. return ObjectData::t___isset(v_name);
  314. }
  315. }
  316. Variant DynamicObjectData::t___unset(Variant v_name) {
  317. if (!parent.isNull()) {
  318. return parent->t___unset(v_name);
  319. } else {
  320. return ObjectData::t___unset(v_name);
  321. }
  322. }
  323. Variant DynamicObjectData::t___sleep() {
  324. if (!parent.isNull()) {
  325. Variant ret = parent->t___sleep();
  326. if (!parent->getAttribute(HasSleep)) {
  327. // When the parent also has the default implementation in ObjectData,
  328. // the attribute HasSleep should be cleared both in the parent and the
  329. // current object.
  330. clearAttribute(HasSleep);
  331. }
  332. return ret;
  333. } else {
  334. return ObjectData::t___sleep();
  335. }
  336. }
  337. Variant DynamicObjectData::t___wakeup() {
  338. if (!parent.isNull()) {
  339. return parent->t___wakeup();
  340. } else {
  341. return ObjectData::t___wakeup();
  342. }
  343. }
  344. Variant DynamicObjectData::t___set_state(Variant v_properties) {
  345. if (!parent.isNull()) {
  346. return parent->t___set_state(v_properties);
  347. } else {
  348. return ObjectData::t___set_state(v_properties);
  349. }
  350. }
  351. String DynamicObjectData::t___tostring() {
  352. if (!parent.isNull()) {
  353. return parent->t___tostring();
  354. } else {
  355. return ObjectData::t___tostring();
  356. }
  357. }
  358. Variant DynamicObjectData::t___clone() {
  359. if (!parent.isNull()) {
  360. return parent->t___clone();
  361. } else {
  362. return ObjectData::t___clone();
  363. }
  364. }
  365. Variant &DynamicObjectData::___lval(Variant v_name) {
  366. if (!parent.isNull()) {
  367. return parent->___lval(v_name);
  368. } else {
  369. return ObjectData::___lval(v_name);
  370. }
  371. }
  372. Variant &DynamicObjectData::___offsetget_lval(Variant v_name) {
  373. if (!parent.isNull()) {
  374. return parent->___offsetget_lval(v_name);
  375. } else {
  376. return ObjectData::___offsetget_lval(v_name);
  377. }
  378. }
  379. ///////////////////////////////////////////////////////////////////////////////
  380. }