2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
6 | Copyright (c) 1997-2010 The PHP Group |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
17 #include "hphp/runtime/ext/wddx/ext_wddx.h"
24 WddxPacket::WddxPacket(const Variant
& comment
, bool manualPacket
, bool sVar
) :
25 m_packetString(""), m_packetClosed(false),
26 m_manualPacketCreation(manualPacket
) {
27 std::string header
= "<header/>";
29 if (!comment
.isNull() && !sVar
) {
30 std::string scomment
= comment
.toString().data();
31 header
= "<header><comment>" + scomment
+ "</comment></header>";
33 m_packetString
= "<wddxPacket version='1.0'>" + header
+ "<data>";
35 if (m_manualPacketCreation
) {
36 m_packetString
= m_packetString
+ "<struct>";
40 bool WddxPacket::add_var(const String
& varName
, bool hasVarTag
) {
41 VarEnv
* v
= g_context
->getVarEnv();
43 Variant varVariant
= *reinterpret_cast<Variant
*>(v
->lookup(varName
.get()));
44 return recursiveAddVar(varName
, varVariant
, hasVarTag
);
47 std::string
WddxPacket::packet_end() {
48 if (!m_packetClosed
) {
49 if (m_manualPacketCreation
) {
50 m_packetString
+= "</struct>";
52 m_packetString
+= "</data></wddxPacket>";
54 m_packetClosed
= true;
55 return m_packetString
;
58 bool WddxPacket::serialize_value(const Variant
& varVariant
) {
59 return recursiveAddVar(empty_string_ref
, varVariant
, false);
62 bool WddxPacket::recursiveAddVar(const String
& varName
,
63 const Variant
& varVariant
,
66 bool isArray
= varVariant
.isArray();
67 bool isObject
= varVariant
.isObject();
69 if (isArray
|| isObject
) {
71 m_packetString
+= "<var name='";
72 m_packetString
+= varName
.data();
73 m_packetString
+= "'>";
77 Object varAsObject
= varVariant
.toObject();
78 if (isArray
) varAsArray
= varVariant
.toArray();
79 if (isObject
) varAsArray
= varAsObject
.toArray();
81 int length
= varAsArray
.length();
83 ArrayIter it
= ArrayIter(varAsArray
);
84 if (it
.first().isString()) isObject
= true;
86 m_packetString
+= "<struct>";
88 m_packetString
+= "<var name='php_class_name'><string>";
89 m_packetString
+= varAsObject
->o_getClassName().c_str();
90 m_packetString
+= "</string></var>";
93 m_packetString
+= "<array length='";
94 m_packetString
+= std::to_string(length
);
95 m_packetString
+= "'>";
97 for (ArrayIter
it(varAsArray
); it
; ++it
) {
98 Variant key
= it
.first();
99 Variant value
= it
.second();
100 recursiveAddVar(key
.toString(), value
, isObject
);
103 m_packetString
+= "</struct>";
106 m_packetString
+= "</array>";
112 m_packetString
+= "<struct>";
114 m_packetString
+= "<var name='php_class_name'><string>";
115 m_packetString
+= varAsObject
->o_getClassName().c_str();
116 m_packetString
+= "</string></var>";
118 m_packetString
+= "</struct>";
122 m_packetString
+= "</var>";
127 std::string varType
= getDataTypeString(varVariant
.getType()).data();
128 if (!getWddxEncoded(varType
, "", varName
, false).empty()) {
129 std::string varValue
= varVariant
.toString().data();
130 if (varType
.compare("boolean") == 0) {
131 varValue
= varVariant
.toBoolean() ? "true" : "false";
133 m_packetString
+= getWddxEncoded(varType
, varValue
, varName
, hasVarTag
);
140 std::string
WddxPacket::getWddxEncoded(const std::string
& varType
,
141 const std::string
& varValue
,
142 const String
& varName
,
144 if (varType
.compare("NULL") == 0) {
145 return wrapValue("<null/>", "", "", varName
, hasVarTag
);
147 if (varType
.compare("boolean") == 0) {
148 return wrapValue("<boolean value='", "'/>", varValue
, varName
, hasVarTag
);
150 if (varType
.compare("integer") == 0 || varType
.compare("double") == 0) {
151 return wrapValue("<number>", "</number>", varValue
, varName
, hasVarTag
);
153 if (varType
.compare("string") == 0) {
154 return wrapValue("<string>", "</string>", varValue
, varName
, hasVarTag
);
159 std::string
WddxPacket::wrapValue(const std::string
& start
,
160 const std::string
& end
,
161 const std::string
& varValue
,
162 const String
& varName
,
164 std::string startVar
= "";
165 std::string endVar
= "";
167 startVar
+= "<var name='";
168 startVar
+= varName
.data();
172 return startVar
+ start
+ varValue
+ end
+ endVar
;
175 //////////////////////////////////////////////////////////////////////////////
178 void find_var_recursive(const TypedValue
* tv
, WddxPacket
* wddxPacket
) {
179 if (tvIsString(tv
)) {
180 String var_name
= tvCastToString(tv
);
181 wddxPacket
->add_var(var_name
, true);
183 if (tv
->m_type
== KindOfArray
) {
184 for (ArrayIter
iter(tv
->m_data
.parr
); iter
; ++iter
) {
185 find_var_recursive(iter
.secondRef().asTypedValue(), wddxPacket
);
190 static TypedValue
* add_vars_helper(ActRec
* ar
) {
192 Resource packet_id
= getArg
<KindOfResource
>(ar
, 0);
193 auto wddxPacket
= packet_id
.getTyped
<WddxPacket
>();
195 for (int i
= start_index
; i
< ar
->numArgs(); i
++) {
196 auto const tv
= getArg(ar
, i
);
197 find_var_recursive(tv
, wddxPacket
);
199 return arReturn(ar
, true);
202 static TypedValue
* serialize_vars_helper(ActRec
* ar
) {
203 WddxPacket
* wddxPacket
= NEWOBJ(WddxPacket
)(empty_string_variant_ref
,
206 for (int i
= start_index
; i
< ar
->numArgs(); i
++) {
207 auto const tv
= getArg(ar
, i
);
208 find_var_recursive(tv
, wddxPacket
);
210 Variant packet
= wddxPacket
->packet_end();
211 return arReturn(ar
, std::move(packet
));
214 //////////////////////////////////////////////////////////////////////////////
217 static TypedValue
* HHVM_FN(wddx_add_vars
)(ActRec
* ar
) {
218 return add_vars_helper(ar
);
221 static TypedValue
* HHVM_FN(wddx_serialize_vars
)(ActRec
* ar
) {
222 return serialize_vars_helper(ar
);
225 static String
HHVM_FUNCTION(wddx_packet_end
, const Resource
& packet_id
) {
226 auto wddxPacket
= packet_id
.getTyped
<WddxPacket
>();
227 std::string packetString
= wddxPacket
->packet_end();
228 return String(packetString
);
231 static Resource
HHVM_FUNCTION(wddx_packet_start
, const Variant
& comment
) {
232 auto wddxPacket
= NEWOBJ(WddxPacket
)(comment
, true, false);
233 return Resource(wddxPacket
);
236 static String
HHVM_FUNCTION(wddx_serialize_value
, const Variant
& var
,
237 const Variant
& comment
) {
238 WddxPacket
* wddxPacket
= NEWOBJ(WddxPacket
)(comment
, false, false);
239 wddxPacket
->serialize_value(var
);
240 const std::string packetString
= wddxPacket
->packet_end();
241 return String(packetString
);
244 //////////////////////////////////////////////////////////////////////////////
246 class wddxExtension
: public Extension
{
248 wddxExtension() : Extension("wddx") {}
249 virtual void moduleInit() {
250 HHVM_FE(wddx_add_vars
);
251 HHVM_FE(wddx_packet_end
);
252 HHVM_FE(wddx_packet_start
);
253 HHVM_FE(wddx_serialize_value
);
254 HHVM_FE(wddx_serialize_vars
);
259 // Uncomment for non-bundled module
260 //HHVM_GET_MODULE(wddx);
262 //////////////////////////////////////////////////////////////////////////////