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()
49 APCSerialize
, //used in APC serialization (controlled by switch)
50 DebuggerSerialize
, //used by hphp debugger for client<->proxy communication
51 PHPOutput
, //used by compiler to output scalar values into byte code
55 * Constructor and destructor.
57 explicit VariableSerializer(Type type
, int option
= 0, int maxRecur
= 3);
58 ~VariableSerializer();
59 VariableSerializer(const VariableSerializer
&) = delete;
60 VariableSerializer
& operator=(const VariableSerializer
&) = delete;
62 // Use UnlimitSerializationScope to suspend this temporarily.
63 static __thread
int64_t serializationSizeLimit
;
66 * Top level entry function called by f_ functions.
68 String
serialize(const Variant
& v
, bool ret
, bool keepCount
= false);
69 String
serializeValue(const Variant
& v
, bool limit
);
71 // Serialize with limit size of output, always return the serialized string.
72 // It does not work with Serialize, JSON, APCSerialize, DebuggerSerialize.
73 String
serializeWithLimit(const Variant
& v
, int limit
);
76 void setDepthLimit(size_t depthLimit
) { m_maxDepth
= depthLimit
; }
77 // for ext_std_variable
78 void incMaxCount() { m_maxCount
++; }
80 Type
getType() const { return m_type
; }
82 enum class ArrayKind
{ PHP
, Dict
, Vec
, Keyset
, VArray
};
86 * Type specialized output functions.
89 void write(char v
) { write((int64_t)v
);}
90 void write(short v
) { write((int64_t)v
);}
91 void write(int v
) { write((int64_t)v
);}
92 void write(int64_t v
);
95 void write(const char *v
, int len
= -1, bool isArrayKey
= false,
96 bool noQuotes
= false);
98 void write(const String
& v
);
99 void write(const Object
& v
);
100 void write(const Variant
& v
, bool isArrayKey
= false);
103 // what to write if recursive level is over limit?
104 void writeOverflow(const TypedValue
& tv
);
105 void writeRefCount(); // for DebugDump only
107 void writeArrayHeader(int size
, bool isVectorData
, ArrayKind kind
);
108 void writeArrayKey(const Variant
& key
, ArrayKind kind
);
109 void writeArrayValue(
110 const Variant
& value
,
113 void writeCollectionKey(
117 void writeArrayFooter(ArrayKind kind
);
118 void writeSerializableObject(const String
& clsname
, const String
& serialized
);
124 void setReferenced(bool referenced
) { m_referenced
= referenced
;}
125 void setRefCount(int count
) { m_refCount
= count
;}
126 bool incNestedLevel(const TypedValue
& tv
);
127 void decNestedLevel(const TypedValue
& tv
);
128 void pushObjectInfo(const String
& objClass
, int objId
, char objCode
);
129 void popObjectInfo();
130 void pushResourceInfo(const String
& rsrcName
, int rsrcId
);
131 void popResourceInfo();
133 // Sentinel used to indicate that a member of SavedRefMap has a count but no ID.
134 static constexpr int NO_ID
= -1;
139 struct MapData
: boost::noncopyable
{
140 MapData() : m_count(0), m_id(-1) { }
145 MapData
& operator[](const TypedValue
& tv
) {
146 auto& elm
= m_mapping
[tv
];
147 if (!elm
.m_count
) tvIncRefGen(tv
);
151 const MapData
& operator[](const TypedValue
& tv
) const {
152 return m_mapping
.at(tv
);
157 std::size_t operator()(const TypedValue
& tv
) const {
158 return pointer_hash
<void>()(tv
.m_data
.parr
);
163 bool operator()(const TypedValue
& a
, const TypedValue
& b
) const {
164 return a
.m_data
.parr
== b
.m_data
.parr
;
168 req::hash_map
<TypedValue
, MapData
, TvHash
, TvEq
> m_mapping
;
172 int m_option
; // type specific extra options
175 SavedRefMap m_refs
; // reference ids and counts for objs/arrays
176 int m_valueCount
; // Current ref index
177 bool m_referenced
; // mark current array element as reference
178 int m_refCount
; // current variable's reference count
179 String m_objClass
; // for object serialization
180 int m_objId
; // for object serialization
181 char m_objCode
; // for object serialization
182 String m_rsrcName
; // for resource serialization
183 int m_rsrcId
; // for resource serialization
184 int m_maxCount
; // for max recursive levels
185 int m_levelDebugger
; // keep track of levels for DebuggerSerialize
186 int m_maxLevelDebugger
; // for max level of DebuggerSerialize
187 size_t m_currentDepth
; // current depth (nasted objects/arrays)
188 size_t m_maxDepth
; // max depth limit before an error (0 -> none)
191 bool is_object
; // nested arrays or objects
192 bool is_vector
; // whether current array is a vector
193 bool first_element
; // whether this is first array element
194 int indent_delta
; // the extra indent to serialize this object
195 int size
; // the number of elements in the array
197 req::vector
<ArrayInfo
> m_arrayInfos
;
206 req::vector
<ObjectInfo
> m_objectInfos
;
208 // The func parameter will be invoked only if there is no overflow.
209 // Otherwise, writeOverflow will be invoked instead.
210 void preventOverflow(const Object
& v
, const std::function
<void()>& func
);
211 void writePropertyKey(const String
& prop
);
213 void serializeRef(const TypedValue
* tv
, bool isArrayKey
);
214 // Serialize a Variant recursively.
215 // The last param noQuotes indicates to serializer to not put the output in
216 // double quotes (used when printing the output of a __toDebugDisplay() of
217 // an object when it is a string.
218 void serializeVariant(const Variant
&,
219 bool isArrayKey
= false,
220 bool skipNestCheck
= false,
221 bool noQuotes
= false);
222 void serializeObject(const Object
&);
223 void serializeObject(const ObjectData
*);
224 void serializeObjectImpl(const ObjectData
* obj
);
225 void serializeCollection(ObjectData
* obj
);
226 void serializeArray(const Array
&, bool isObject
= false);
227 void serializeArray(const ArrayData
*, bool skipNestCheck
= false);
228 void serializeArrayImpl(const ArrayData
* arr
);
229 void serializeResource(const ResourceData
*);
230 void serializeResourceImpl(const ResourceData
* res
);
231 void serializeString(const String
&);
233 Array
getSerializeProps(const ObjectData
* obj
) const;
236 // TODO: Move to util/folly?
237 template<typename T
> struct TmpAssign
{
238 TmpAssign(T
& v
, const T tmp
) : cur(v
), save(cur
) { cur
= tmp
; }
239 ~TmpAssign() { cur
= save
; }
244 struct UnlimitSerializationScope
{
245 static constexpr int32_t kTmpLimit
= StringData::MaxSize
;
246 TmpAssign
<int64_t> v
{VariableSerializer::serializationSizeLimit
, kTmpLimit
};
247 TmpAssign
<int64_t> rs
{RuntimeOption::SerializationSizeLimit
, kTmpLimit
};
248 TmpAssign
<int32_t> rm
{RuntimeOption::MaxSerializedStringSize
, kTmpLimit
};
251 extern const StaticString s_serializedNativeDataKey
;
253 ///////////////////////////////////////////////////////////////////////////////
256 #endif // incl_HPHP_VARIABLE_SERIALIZER_H_