/hphp/runtime/base/array/array_init.h

https://bitbucket.org/gnanakeethan/hiphop-php · C Header · 320 lines · 245 code · 41 blank · 34 comment · 36 complexity · fb2c91625ad7218f03b43fcfb25be556 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. #ifndef incl_HPHP_ARRAY_INIT_H_
  17. #define incl_HPHP_ARRAY_INIT_H_
  18. #include "hphp/runtime/base/array/array_data.h"
  19. #include "hphp/runtime/base/complex_types.h"
  20. namespace HPHP {
  21. ///////////////////////////////////////////////////////////////////////////////
  22. // macros for creating vectors or maps
  23. #define CREATE_VECTOR1(e) \
  24. Array(ArrayInit(1, ArrayInit::vectorInit).set(e).create())
  25. #define CREATE_VECTOR2(e1, e2) \
  26. Array(ArrayInit(2, ArrayInit::vectorInit).set(e1).set(e2).create())
  27. #define CREATE_VECTOR3(e1, e2, e3) \
  28. Array(ArrayInit(3, ArrayInit::vectorInit).set(e1).set(e2).set(e3).create())
  29. #define CREATE_VECTOR4(e1, e2, e3, e4) \
  30. Array(ArrayInit(4, ArrayInit::vectorInit).set(e1).set(e2).set(e3). \
  31. set(e4).create())
  32. #define CREATE_VECTOR5(e1, e2, e3, e4, e5) \
  33. Array(ArrayInit(5, ArrayInit::vectorInit).set(e1).set(e2).set(e3). \
  34. set(e4).set(e5).create())
  35. #define CREATE_VECTOR6(e1, e2, e3, e4, e5, e6) \
  36. Array(ArrayInit(6, ArrayInit::vectorInit).set(e1).set(e2).set(e3). \
  37. set(e4).set(e5).set(e6).create())
  38. inline String initkey(const char* s) { return String(s); }
  39. inline int64_t initkey(int k) { return k; }
  40. inline int64_t initkey(int64_t k) { return k; }
  41. inline CStrRef initkey(CStrRef k) { return k; }
  42. #define CREATE_MAP1(n, e) Array(ArrayInit(1).set(initkey(n), e).create())
  43. #define CREATE_MAP2(n1, e1, n2, e2)\
  44. Array(ArrayInit(2).set(initkey(n1), e1)\
  45. .set(initkey(n2), e2).create())
  46. #define CREATE_MAP3(n1, e1, n2, e2, n3, e3)\
  47. Array(ArrayInit(3).set(initkey(n1), e1)\
  48. .set(initkey(n2), e2)\
  49. .set(initkey(n3), e3).create())
  50. #define CREATE_MAP4(n1, e1, n2, e2, n3, e3, n4, e4)\
  51. Array(ArrayInit(4).set(initkey(n1), e1)\
  52. .set(initkey(n2), e2)\
  53. .set(initkey(n3), e3)\
  54. .set(initkey(n4), e4).create())
  55. #define CREATE_MAP5(n1, e1, n2, e2, n3, e3, n4, e4, n5, e5)\
  56. Array(ArrayInit(5).set(initkey(n1), e1)\
  57. .set(initkey(n2), e2)\
  58. .set(initkey(n3), e3)\
  59. .set(initkey(n4), e4)\
  60. .set(initkey(n5), e5).create())
  61. #define CREATE_MAP6(n1, e1, n2, e2, n3, e3, n4, e4, n5, e5, n6, e6)\
  62. Array(ArrayInit(6).set(initkey(n1), e1)\
  63. .set(initkey(n2), e2)\
  64. .set(initkey(n3), e3)\
  65. .set(initkey(n4), e4)\
  66. .set(initkey(n5), e5)\
  67. .set(initkey(n6), e6).create())
  68. ///////////////////////////////////////////////////////////////////////////////
  69. // ArrayInit
  70. /**
  71. * When an Array is created, ArrayInit completely skips the use of
  72. * ArrayElement, (the set methods mimic the constructors of ArrayElement).
  73. * The setRef method handles the case where the value needs to be a reference.
  74. *
  75. * For arrays that need to have C++ references/pointers to their elements for
  76. * an extended period of time, set keepRef to true, so that there will not
  77. * be reference-breaking escalation.
  78. */
  79. class ArrayInit {
  80. public:
  81. enum VectorInit { vectorInit };
  82. enum MapInit { mapInit };
  83. explicit ArrayInit(ssize_t n);
  84. ArrayInit(ssize_t n, VectorInit) {
  85. m_data = CreateVector(n);
  86. }
  87. ArrayInit(ssize_t n, MapInit) {
  88. m_data = CreateMap(n);
  89. }
  90. ArrayInit(ArrayInit&& other) : m_data(other.m_data) {
  91. other.m_data = nullptr;
  92. }
  93. ArrayInit(const ArrayInit&) = delete;
  94. ArrayInit& operator=(const ArrayInit&) = delete;
  95. static ArrayData *CreateVector(ssize_t n);
  96. static ArrayData *CreateMap(ssize_t n);
  97. ~ArrayInit() {
  98. // In case an exception interrupts the initialization.
  99. if (m_data) m_data->release();
  100. }
  101. ArrayInit &set(CVarRef v) {
  102. m_data->append(v, false);
  103. return *this;
  104. }
  105. ArrayInit &set(RefResult v) {
  106. setRef(variant(v));
  107. return *this;
  108. }
  109. ArrayInit &set(CVarWithRefBind v) {
  110. m_data->appendWithRef(variant(v), false);
  111. return *this;
  112. }
  113. ArrayInit &setRef(CVarRef v) {
  114. m_data->appendRef(v, false);
  115. return *this;
  116. }
  117. ArrayInit &set(int64_t name, CVarRef v, bool keyConverted = false) {
  118. m_data->set(name, v, false);
  119. return *this;
  120. }
  121. // set(const char*) deprecated. Use set(CStrRef) with a StaticString,
  122. // if you have a literal, or String otherwise.
  123. ArrayInit &set(const char*, CVarRef v, bool keyConverted = false) = delete;
  124. ArrayInit &set(CStrRef name, CVarRef v, bool keyConverted = false) {
  125. if (keyConverted) {
  126. m_data->set(name, v, false);
  127. } else if (!name.isNull()) {
  128. m_data->set(name.toKey(), v, false);
  129. }
  130. return *this;
  131. }
  132. ArrayInit &set(CVarRef name, CVarRef v, bool keyConverted = false) {
  133. if (keyConverted) {
  134. m_data->set(name, v, false);
  135. } else {
  136. VarNR k(name.toKey());
  137. if (!k.isNull()) {
  138. m_data->set(k, v, false);
  139. }
  140. }
  141. return *this;
  142. }
  143. template<typename T>
  144. ArrayInit &set(const T &name, CVarRef v, bool keyConverted = false) {
  145. if (keyConverted) {
  146. m_data->set(name, v, false);
  147. } else {
  148. VarNR k(Variant(name).toKey());
  149. if (!k.isNull()) {
  150. m_data->set(k, v, false);
  151. }
  152. }
  153. return *this;
  154. }
  155. ArrayInit &set(CStrRef name, RefResult v, bool keyConverted = false) {
  156. if (keyConverted) {
  157. m_data->setRef(name, variant(v), false);
  158. } else if (!name.isNull()) {
  159. m_data->setRef(name.toKey(), variant(v), false);
  160. }
  161. return *this;
  162. }
  163. ArrayInit &set(CVarRef name, RefResult v, bool keyConverted = false) {
  164. if (keyConverted) {
  165. m_data->setRef(name, variant(v), false);
  166. } else {
  167. VarNR k(name.toKey());
  168. if (!k.isNull()) {
  169. m_data->setRef(k, variant(v), false);
  170. }
  171. }
  172. return *this;
  173. }
  174. template<typename T>
  175. ArrayInit &set(const T &name, RefResult v, bool keyConverted = false) {
  176. if (keyConverted) {
  177. m_data->setRef(name, variant(v), false);
  178. } else {
  179. VarNR k(Variant(name).toKey());
  180. if (!k.isNull()) {
  181. m_data->setRef(k, variant(v), false);
  182. }
  183. }
  184. return *this;
  185. }
  186. ArrayInit &add(int64_t name, CVarRef v, bool keyConverted = false) {
  187. m_data->add(name, v, false);
  188. return *this;
  189. }
  190. ArrayInit &add(CStrRef name, CVarRef v, bool keyConverted = false) {
  191. if (keyConverted) {
  192. m_data->add(name, v, false);
  193. } else if (!name.isNull()) {
  194. m_data->add(name.toKey(), v, false);
  195. }
  196. return *this;
  197. }
  198. ArrayInit &add(CVarRef name, CVarRef v, bool keyConverted = false) {
  199. if (keyConverted) {
  200. m_data->add(name, v, false);
  201. } else {
  202. VarNR k(name.toKey());
  203. if (!k.isNull()) {
  204. m_data->add(k, v, false);
  205. }
  206. }
  207. return *this;
  208. }
  209. template<typename T>
  210. ArrayInit &add(const T &name, CVarRef v, bool keyConverted = false) {
  211. if (keyConverted) {
  212. m_data->add(name, v, false);
  213. } else {
  214. VarNR k(Variant(name).toKey());
  215. if (!k.isNull()) {
  216. m_data->add(k, v, false);
  217. }
  218. }
  219. return *this;
  220. }
  221. ArrayInit &setRef(int64_t name, CVarRef v, bool keyConverted = false) {
  222. m_data->setRef(name, v, false);
  223. return *this;
  224. }
  225. ArrayInit &setRef(CStrRef name, CVarRef v, bool keyConverted = false) {
  226. if (keyConverted) {
  227. m_data->setRef(name, v, false);
  228. } else {
  229. m_data->setRef(name.toKey(), v, false);
  230. }
  231. return *this;
  232. }
  233. ArrayInit &setRef(CVarRef name, CVarRef v, bool keyConverted = false) {
  234. if (keyConverted) {
  235. m_data->setRef(name, v, false);
  236. } else {
  237. Variant key(name.toKey());
  238. if (!key.isNull()) {
  239. m_data->setRef(key, v, false);
  240. }
  241. }
  242. return *this;
  243. }
  244. template<typename T>
  245. ArrayInit &setRef(const T &name, CVarRef v, bool keyConverted = false) {
  246. if (keyConverted) {
  247. m_data->setRef(name, v, false);
  248. } else {
  249. VarNR key(Variant(name).toKey());
  250. if (!key.isNull()) {
  251. m_data->setRef(key, v, false);
  252. }
  253. }
  254. return *this;
  255. }
  256. // Prefer toArray() in new code---it can save a null check when the
  257. // compiler can't prove m_data hasn't changed.
  258. ArrayData *create() {
  259. ArrayData *ret = m_data;
  260. m_data = nullptr;
  261. return ret;
  262. }
  263. Array toArray() {
  264. auto ptr = m_data;
  265. m_data = nullptr;
  266. return Array(ptr, Array::ArrayInitCtor::Tag);
  267. }
  268. Variant toVariant() {
  269. auto ptr = m_data;
  270. m_data = nullptr;
  271. return Variant(ptr, Variant::ArrayInitCtor::Tag);
  272. }
  273. static ArrayData *CreateParams(int count, ...);
  274. private:
  275. ArrayData *m_data;
  276. };
  277. ///////////////////////////////////////////////////////////////////////////////
  278. }
  279. #endif /* incl_HPHP_ARRAY_INIT_H_ */