Clean up APCTypedValue a bit.
[hiphop-php.git] / hphp / runtime / base / apc-handle.cpp
blob50424bdfd933e8700616a57ee38cdb00f8d34b5d
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2015 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 +----------------------------------------------------------------------+
16 #include "hphp/runtime/base/apc-handle.h"
18 #include "hphp/runtime/base/apc-typed-value.h"
19 #include "hphp/runtime/base/apc-string.h"
20 #include "hphp/runtime/base/apc-array.h"
21 #include "hphp/runtime/base/apc-object.h"
22 #include "hphp/runtime/base/apc-collection.h"
23 #include "hphp/runtime/base/mixed-array.h"
24 #include "hphp/runtime/ext/apc/ext_apc.h"
26 namespace HPHP {
28 //////////////////////////////////////////////////////////////////////
30 APCHandle::Pair APCHandle::Create(const Variant& source,
31 bool serialized,
32 bool inner,
33 bool unserializeObj) {
34 auto type = source.getType(); // this gets rid of the ref, if it was one
35 switch (type) {
36 case KindOfUninit: {
37 auto value = APCTypedValue::tvUninit();
38 return {value->getHandle(), sizeof(APCTypedValue)};
40 case KindOfNull: {
41 auto value = APCTypedValue::tvNull();
42 return {value->getHandle(), sizeof(APCTypedValue)};
44 case KindOfBoolean: {
45 auto value = source.getBoolean() ? APCTypedValue::tvTrue()
46 : APCTypedValue::tvFalse();
47 return {value->getHandle(), sizeof(APCTypedValue)};
49 case KindOfInt64: {
50 auto value = new APCTypedValue(source.getInt64());
51 return {value->getHandle(), sizeof(APCTypedValue)};
53 case KindOfDouble: {
54 auto value = new APCTypedValue(source.getDouble());
55 return {value->getHandle(), sizeof(APCTypedValue)};
57 case KindOfStaticString: {
58 StringData* s = source.getStringData();
59 if (serialized) {
60 // It is priming, and there might not be the right class definitions
61 // for unserialization.
62 return APCObject::MakeSerializedObj(apc_reserialize(String{s}));
64 auto value = new APCTypedValue(APCTypedValue::StaticStr{}, s);
65 return {value->getHandle(), sizeof(APCTypedValue)};
67 case KindOfString: {
68 StringData* s = source.getStringData();
69 if (serialized) {
70 // It is priming, and there might not be the right class definitions
71 // for unserialization.
72 return APCObject::MakeSerializedObj(apc_reserialize(String{s}));
75 auto const st = lookupStaticString(s);
76 if (st) {
77 auto value = new APCTypedValue(APCTypedValue::StaticStr{}, st);
78 return {value->getHandle(), sizeof(APCTypedValue)};
81 assert(!s->isStatic()); // would've been handled above
82 if (!inner && apcExtension::UseUncounted) {
83 auto st = StringData::MakeUncounted(s->slice());
84 auto value = new APCTypedValue(APCTypedValue::UncountedStr{}, st);
85 return {value->getHandle(), st->size() + sizeof(APCTypedValue)};
87 return APCString::MakeSharedString(type, s);
90 case KindOfArray:
91 return APCArray::MakeSharedArray(source.getArrayData(), inner,
92 unserializeObj);
94 case KindOfObject:
95 if (source.getObjectData()->isCollection()) {
96 return APCCollection::Make(source.getObjectData(),
97 inner,
98 unserializeObj);
100 return unserializeObj ? APCObject::Construct(source.getObjectData()) :
101 APCObject::MakeSerializedObj(apc_serialize(source));
103 case KindOfResource:
104 // TODO Task #2661075: Here and elsewhere in the runtime, we convert
105 // Resources to the empty array during various serialization operations,
106 // which does not match Zend behavior. We should fix this.
107 return APCArray::MakeSharedEmptyArray();
109 case KindOfRef:
110 case KindOfClass:
111 return {nullptr, 0};
113 not_reached();
116 Variant APCHandle::toLocal() const {
117 switch (m_type) {
118 case KindOfUninit:
119 case KindOfNull:
120 return init_null(); // shortcut.. no point to forward
121 case KindOfBoolean:
122 return APCTypedValue::fromHandle(this)->getBoolean();
123 case KindOfInt64:
124 return APCTypedValue::fromHandle(this)->getInt64();
125 case KindOfDouble:
126 return APCTypedValue::fromHandle(this)->getDouble();
127 case KindOfStaticString:
128 return Variant{APCTypedValue::fromHandle(this)->getStringData()};
129 case KindOfString:
130 return APCString::MakeString(this);
131 case KindOfArray:
132 return APCArray::MakeArray(this);
133 case KindOfObject:
134 return APCObject::MakeObject(this);
135 case KindOfResource:
136 case KindOfRef:
137 case KindOfClass:
138 break;
140 not_reached();
143 void APCHandle::deleteShared() {
144 assert(!isUncounted());
145 switch (m_type) {
146 case KindOfUninit:
147 case KindOfNull:
148 case KindOfBoolean:
149 return;
150 case KindOfInt64:
151 case KindOfDouble:
152 case KindOfStaticString:
153 delete APCTypedValue::fromHandle(this);
154 return;
156 case KindOfString:
157 APCString::Delete(APCString::fromHandle(this));
158 return;
160 case KindOfArray:
161 APCArray::Delete(this);
162 return;
164 case KindOfObject:
165 if (isAPCCollection()) {
166 APCCollection::Delete(this);
167 return;
169 APCObject::Delete(this);
170 return;
172 case KindOfResource:
173 case KindOfRef:
174 case KindOfClass:
175 break;
177 not_reached();
180 //////////////////////////////////////////////////////////////////////