2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present 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 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_VARIABLE_SERIALIZER_H_
18 #define incl_HPHP_VARIABLE_SERIALIZER_H_
20 #include "hphp/runtime/base/string-buffer.h"
21 #include "hphp/runtime/base/string-data.h"
22 #include "hphp/runtime/base/runtime-option.h"
23 #include "hphp/runtime/base/req-containers.h"
24 #include "hphp/runtime/base/tv-mutate.h"
25 #include "hphp/runtime/base/tv-variant.h"
26 #include "hphp/runtime/vm/class.h"
28 #include <boost/noncopyable.hpp>
31 ///////////////////////////////////////////////////////////////////////////////
34 * Maintaining states during serialization of a variable. We use this single
35 * class to uniformly serialize variables according to different formats.
37 struct VariableSerializer
{
43 VarExport
, //var_export()
45 DebugDump
, //debug_zval_dump()
46 DebuggerDump
, //used by hphp debugger to obtain user visible output
47 Serialize
, // serialize()
48 Internal
, // used internally by the compiler. No compatibility guarantees.
50 APCSerialize
, //used in APC serialization (controlled by switch)
51 DebuggerSerialize
, //used by hphp debugger for client<->proxy communication
52 PHPOutput
, //used by compiler to output scalar values into byte code
56 * Constructor and destructor.
58 explicit VariableSerializer(Type type
, int option
= 0, int maxRecur
= 3);
59 ~VariableSerializer();
60 VariableSerializer(const VariableSerializer
&) = delete;
61 VariableSerializer
& operator=(const VariableSerializer
&) = delete;
63 // Use UnlimitSerializationScope to suspend this temporarily.
64 static __thread
int64_t serializationSizeLimit
;
67 * Top level entry function called by f_ functions.
69 String
serialize(const Variant
& v
, bool ret
, bool keepCount
= false);
70 String
serializeValue(const Variant
& v
, bool limit
);
72 // Serialize with limit size of output, always return the serialized string.
73 // It does not work with Serialize, JSON, APCSerialize, DebuggerSerialize.
74 String
serializeWithLimit(const Variant
& v
, int limit
);
77 void setDepthLimit(size_t depthLimit
) { m_maxDepth
= depthLimit
; }
78 // for ext_std_variable
79 void incMaxCount() { m_maxCount
++; }
81 Type
getType() const { return m_type
; }
83 // By default, for Type::Serialize, d/varrays are serialized as normal
84 // arrays. This flag can override that behavior.
85 void keepDVArrays() { m_keepDVArrays
= true; }
87 // Force Hack arrays to serialize as PHP arrays
88 void setForcePHPArrays() { m_forcePHPArrays
= true; }
90 // Emit a Hack array compat notice on Hack array serialization
91 void setHackWarn() { m_hackWarn
= true; }
93 // Emit a Hack array compat notice on PHP array serialization
94 void setPHPWarn() { m_phpWarn
= true; }
96 enum class ArrayKind
{ PHP
, Dict
, Vec
, Keyset
, VArray
, DArray
};
100 * Type specialized output functions.
103 void write(char v
) { write((int64_t)v
);}
104 void write(short v
) { write((int64_t)v
);}
105 void write(int v
) { write((int64_t)v
);}
106 void write(int64_t v
);
107 void write(double v
);
109 void write(const char *v
, int len
= -1, bool isArrayKey
= false,
110 bool noQuotes
= false);
112 void write(const String
& v
);
113 void write(const Object
& v
);
114 void write(const Variant
& v
, bool isArrayKey
= false);
117 // what to write if recursive level is over limit?
118 void writeOverflow(const TypedValue
& tv
);
119 void writeRefCount(); // for DebugDump only
121 void writeArrayHeader(int size
, bool isVectorData
, ArrayKind kind
);
122 void writeArrayKey(const Variant
& key
, ArrayKind kind
);
123 void writeArrayValue(
124 const Variant
& value
,
127 void writeCollectionKey(
131 void writeArrayFooter(ArrayKind kind
);
132 void writeSerializableObject(const String
& clsname
, const String
& serialized
);
138 void setReferenced(bool referenced
) { m_referenced
= referenced
;}
139 void setRefCount(int count
) { m_refCount
= count
;}
140 bool incNestedLevel(const TypedValue
& tv
);
141 void decNestedLevel(const TypedValue
& tv
);
142 void pushObjectInfo(const String
& objClass
, int objId
, char objCode
);
143 void popObjectInfo();
144 void pushResourceInfo(const String
& rsrcName
, int rsrcId
);
145 void popResourceInfo();
147 ArrayKind
getKind(const ArrayData
* arr
) const;
149 // Sentinel used to indicate that a member of SavedRefMap has a count but no ID.
150 static constexpr int NO_ID
= -1;
155 struct MapData
: boost::noncopyable
{
156 MapData() : m_count(0), m_id(-1) { }
161 MapData
& operator[](const TypedValue
& tv
) {
162 auto& elm
= m_mapping
[tv
];
163 if (!elm
.m_count
) tvIncRefGen(tv
);
167 const MapData
& operator[](const TypedValue
& tv
) const {
168 return m_mapping
.at(tv
);
173 std::size_t operator()(const TypedValue
& tv
) const {
174 return pointer_hash
<void>()(tv
.m_data
.parr
);
179 bool operator()(const TypedValue
& a
, const TypedValue
& b
) const {
180 return a
.m_data
.parr
== b
.m_data
.parr
;
184 req::hash_map
<TypedValue
, MapData
, TvHash
, TvEq
> m_mapping
;
188 int m_option
; // type specific extra options
191 SavedRefMap m_refs
; // reference ids and counts for objs/arrays
192 int m_valueCount
; // Current ref index
193 bool m_referenced
; // mark current array element as reference
194 bool m_keepDVArrays
; // serialize d/varrays as themselves or arrays
195 bool m_forcePHPArrays
; // serialize PHP and Hack arrays as PHP arrays
196 bool m_hackWarn
; // warn when attempting on Hack arrays
197 bool m_phpWarn
; // warn when attempting on PHP arrays
198 bool m_hasHackWarned
; // have we already warned on Hack arrays?
199 bool m_hasPHPWarned
; // have we already warned on PHP arrays?
200 int m_refCount
; // current variable's reference count
201 String m_objClass
; // for object serialization
202 int m_objId
; // for object serialization
203 char m_objCode
; // for object serialization
204 String m_rsrcName
; // for resource serialization
205 int m_rsrcId
; // for resource serialization
206 int m_maxCount
; // for max recursive levels
207 int m_levelDebugger
; // keep track of levels for DebuggerSerialize
208 int m_maxLevelDebugger
; // for max level of DebuggerSerialize
209 size_t m_currentDepth
; // current depth (nasted objects/arrays)
210 size_t m_maxDepth
; // max depth limit before an error (0 -> none)
213 bool is_object
; // nested arrays or objects
214 bool is_vector
; // whether current array is a vector
215 bool first_element
; // whether this is first array element
216 int indent_delta
; // the extra indent to serialize this object
217 int size
; // the number of elements in the array
219 req::vector
<ArrayInfo
> m_arrayInfos
;
228 req::vector
<ObjectInfo
> m_objectInfos
;
230 // The func parameter will be invoked only if there is no overflow.
231 // Otherwise, writeOverflow will be invoked instead.
232 void preventOverflow(const Object
& v
, const std::function
<void()>& func
);
233 void writePropertyKey(const String
& prop
);
235 void serializeRef(const TypedValue
* tv
, bool isArrayKey
);
236 // Serialize a Variant recursively.
237 // The last param noQuotes indicates to serializer to not put the output in
238 // double quotes (used when printing the output of a __toDebugDisplay() of
239 // an object when it is a string.
240 void serializeVariant(const Variant
&,
241 bool isArrayKey
= false,
242 bool skipNestCheck
= false,
243 bool noQuotes
= false);
244 void serializeObject(const Object
&);
245 void serializeObject(const ObjectData
*);
246 void serializeObjectImpl(const ObjectData
* obj
);
247 void serializeCollection(ObjectData
* obj
);
248 void serializeArray(const Array
&, bool isObject
= false);
249 void serializeArray(const ArrayData
*, bool skipNestCheck
= false);
250 void serializeArrayImpl(const ArrayData
* arr
);
251 void serializeResource(const ResourceData
*);
252 void serializeResourceImpl(const ResourceData
* res
);
253 void serializeString(const String
&);
255 Array
getSerializeProps(const ObjectData
* obj
) const;
258 inline String
internal_serialize(const Variant
& v
) {
259 VariableSerializer vs
{VariableSerializer::Type::Internal
};
260 return vs
.serializeValue(v
, false);
263 // TODO: Move to util/folly?
264 template<typename T
> struct TmpAssign
{
265 TmpAssign(T
& v
, const T tmp
) : cur(v
), save(cur
) { cur
= tmp
; }
266 ~TmpAssign() { cur
= save
; }
271 struct UnlimitSerializationScope
{
272 static constexpr int32_t kTmpLimit
= StringData::MaxSize
;
273 TmpAssign
<int64_t> v
{VariableSerializer::serializationSizeLimit
, kTmpLimit
};
274 TmpAssign
<int64_t> rs
{RuntimeOption::SerializationSizeLimit
, kTmpLimit
};
275 TmpAssign
<int32_t> rm
{RuntimeOption::MaxSerializedStringSize
, kTmpLimit
};
278 extern const StaticString s_serializedNativeDataKey
;
280 ///////////////////////////////////////////////////////////////////////////////
283 #endif // incl_HPHP_VARIABLE_SERIALIZER_H_