codemod 2010-2016 to 2010-present
[hiphop-php.git] / hphp / runtime / base / thrift-buffer.cpp
blob9369eeb476c2b912b730ea5b48b498b696f379f7
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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 #include "hphp/runtime/base/thrift-buffer.h"
19 #include "hphp/runtime/base/builtin-functions.h"
20 #include "hphp/runtime/base/type-conversions.h"
21 #include "hphp/runtime/base/variable-unserializer.h"
23 #include "hphp/util/logger.h"
25 #include <vector>
27 #define INVALID_DATA 1
29 namespace HPHP {
30 ///////////////////////////////////////////////////////////////////////////////
32 ThriftBuffer::ThriftBuffer(int size,
33 VariableSerializer::Type sType /* = Serialize*/)
34 : m_size(size), m_safe(false), m_serializerType(sType) {
35 m_buf = (char *)malloc(m_size + 1);
36 if (!m_buf) throwOutOfMemory();
37 m_pEnd = m_buf + m_size;
38 m_pSafe = m_pEnd - sizeof(int64_t) - 1;
39 m_p = m_buf;
42 ThriftBuffer::~ThriftBuffer() {
43 free(m_buf);
46 void ThriftBuffer::reset(bool read) {
47 if (read) {
48 m_pEnd = m_buf;
49 m_safe = false;
50 } else {
51 m_pEnd = m_buf + m_size;
53 m_pSafe = m_pEnd - sizeof(int64_t) - 1;
54 m_p = m_buf;
57 ///////////////////////////////////////////////////////////////////////////////
59 void ThriftBuffer::write(const String& data) {
60 int32_t len = data.size();
61 write(len);
63 if (m_p + len > m_pEnd) {
64 flush();
66 if (len > m_size) {
67 flushImpl(data);
68 } else {
69 memcpy(m_p, data.data(), len);
70 if ((m_p += len) > m_pSafe) flush();
74 void ThriftBuffer::flush() {
75 *m_p = '\0';
76 String data(m_buf, m_p - m_buf, CopyString);
77 m_p = m_buf;
78 flushImpl(data);
81 ///////////////////////////////////////////////////////////////////////////////
83 void ThriftBuffer::read(char *data, int len) {
84 int avail = m_pEnd - m_p;
86 // still enough
87 if (avail >= len) {
88 if (data) memcpy(data, m_p, len);
89 if ((m_p += len) > m_pSafe) m_safe = false;
90 return;
93 if (data) memcpy(data, m_p, avail);
94 len -= avail;
95 data += avail;
97 while (true) {
98 String ret = readImpl();
99 if (ret.empty()) {
100 throwError("unable to read enough bytes",INVALID_DATA);
103 const char *rdata = ret.data();
104 int rsize = ret.size();
106 if (rsize >= len) {
107 if (data) memcpy(data, rdata, len);
108 rsize -= len;
109 if (rsize) {
110 memcpy(m_buf, rdata + len, rsize);
111 m_pEnd = m_buf + rsize;
112 } else {
113 m_pEnd = m_buf;
115 m_pSafe = m_pEnd - sizeof(int64_t) - 1;
116 m_p = m_buf;
117 if (m_p > m_pSafe) m_safe = false;
118 return; // done
121 if (data) memcpy(data, rdata, rsize);
122 len -= rsize;
123 data += rsize;
127 void ThriftBuffer::skip(int8_t type) {
128 switch (type) {
129 case T_STOP:
130 case T_VOID:
131 return;
132 case T_STRUCT:
133 while (true) {
134 int8_t ttype; read(ttype); // get field type
135 if (ttype == T_STOP) break;
136 read(nullptr, 2); // skip field number, I16
137 skip(ttype); // skip field payload
139 return;
140 case T_BOOL:
141 case T_BYTE:
142 read(nullptr, 1);
143 return;
144 case T_I16:
145 read(nullptr, 2);
146 return;
147 case T_I32:
148 read(nullptr, 4);
149 return;
150 case T_U64:
151 case T_I64:
152 case T_DOUBLE:
153 read(nullptr, 8);
154 return;
155 //case T_UTF7: // aliases T_STRING
156 case T_UTF8:
157 case T_UTF16:
158 case T_STRING: {
159 int32_t len; read(len);
160 read(nullptr, len);
161 } return;
162 case T_MAP: {
163 int8_t keytype; read(keytype);
164 int8_t valtype; read(valtype);
165 int32_t size; read(size);
166 for (int32_t i = 0; i < size; ++i) {
167 skip(keytype);
168 skip(valtype);
170 } return;
171 case T_LIST:
172 case T_SET: {
173 int8_t valtype; read(valtype);
174 int32_t size; read(size);
175 for (int32_t i = 0; i < size; ++i) {
176 skip(valtype);
178 } return;
181 char errbuf[128];
182 sprintf(errbuf, "Unknown field type: %d", (int)type);
183 throwError(errbuf, INVALID_DATA);
186 void ThriftBuffer::throwOutOfMemory() {
187 throwError("out of memory", 0);
190 void ThriftBuffer::throwInvalidStringSize(int size) {
191 char errbuf[128];
192 sprintf(errbuf, "Negative string size: %d", (int)size);
193 throwError(errbuf, INVALID_DATA);
196 ///////////////////////////////////////////////////////////////////////////////
198 static Variant unserialize_with_no_notice(const String& str) {
199 VariableUnserializer vu(str.data(), str.size(),
200 VariableUnserializer::Type::Serialize, true);
201 Variant v;
202 try {
203 v = vu.unserialize();
204 } catch (ResourceExceededException &) {
205 throw;
206 } catch (Exception &e) {
207 Logger::Error("unserialize(): %s", e.getMessage().c_str());
209 return v;
212 void ThriftBuffer::read(std::string &data) {
213 String sdata;
214 read(sdata);
215 data = std::string(sdata.data(), sdata.size());
218 void ThriftBuffer::write(const std::string &data) {
219 write(String(data.data(), data.size(), CopyString));
222 void ThriftBuffer::read(std::vector<std::string> &data) {
223 int32_t size;
224 read(size);
225 data.resize(size);
226 for (int i = 0; i < size; i++) {
227 read(data[i]);
231 void ThriftBuffer::write(const std::vector<std::string> &data) {
232 int32_t size = data.size();
233 write(size);
234 for (int i = 0; i < size; i++) {
235 write(data[i]);
239 void ThriftBuffer::read(Array &data) {
240 String sdata;
241 read(sdata);
242 data = unserialize_with_no_notice(sdata).toArray();
245 void ThriftBuffer::write(const Array& data) {
246 VariableSerializer vs(m_serializerType);
247 String sdata = vs.serialize(VarNR(data), true);
248 write(sdata);
251 void ThriftBuffer::read(Object &data) {
252 String sdata;
253 read(sdata);
254 data = unserialize_with_no_notice(sdata).toObject();
257 void ThriftBuffer::write(const Object& data) {
258 VariableSerializer vs(m_serializerType);
259 String sdata = vs.serialize(VarNR(data), true);
260 write(sdata);
263 void ThriftBuffer::read(Variant &data) {
264 String sdata;
265 read(sdata);
266 data = unserialize_with_no_notice(sdata);
269 void ThriftBuffer::write(const Variant& data) {
270 VariableSerializer vs(m_serializerType);
271 String sdata = vs.serialize(data, true);
272 write(sdata);
275 ///////////////////////////////////////////////////////////////////////////////