Arquivos
hhvm/hphp/runtime/base/variable_unserializer.h
T
mwilliams 39ba801ffc More smart containers
And use them for VariableSerializer/VariableUnserializer
2013-04-04 12:20:04 -07:00

138 linhas
4.5 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef __HPHP_VARIABLE_UNSERIALIZER_H__
#define __HPHP_VARIABLE_UNSERIALIZER_H__
#include <runtime/base/types.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
class VariableUnserializer {
public:
/**
* Supported formats.
*/
enum Type {
Serialize,
APCSerialize,
};
public:
VariableUnserializer(const char *str, size_t len, Type type,
bool allowUnknownSerializableClass = false)
: m_type(type), m_buf(str), m_end(str + len),
m_unknownSerializable(allowUnknownSerializableClass) {}
VariableUnserializer(const char *str, const char *end, Type type,
bool allowUnknownSerializableClass = false)
: m_type(type), m_buf(str), m_end(end),
m_unknownSerializable(allowUnknownSerializableClass) {}
Type getType() const { return m_type;}
bool allowUnknownSerializableClass() const { return m_unknownSerializable;}
Variant unserialize();
Variant unserializeKey();
void add(Variant* v, Uns::Mode mode) {
if (mode == Uns::ValueMode) {
m_refs.emplace_back(RefInfo(v));
} else if (mode == Uns::KeyMode) {
// do nothing
} else if (mode == Uns::ColValueMode) {
m_refs.emplace_back(RefInfo::makeNonRefable(v));
} else {
assert(mode == Uns::ColKeyMode);
// We don't currently support using the 'r' encoding to refer
// to collection keys, but eventually we'll need to make this
// work to allow objects as keys. For now we encode collections
// keys in m_refs using a null pointer.
m_refs.emplace_back(RefInfo(nullptr));
}
}
// getByVal() is used to resolve the 'r' encoding
Variant* getByVal(int id) {
if (id <= 0 || id > (int)m_refs.size()) return nullptr;
Variant* ret = m_refs[id-1].var();
if (!ret) {
throw Exception("Referring to collection keys using the 'r' encoding "
"is not supported");
}
return ret;
}
// getByVal() is used to resolve the 'R' encoding
Variant* getByRef(int id) {
if (id <= 0 || id > (int)m_refs.size()) return nullptr;
if (!m_refs[id-1].canBeReferenced()) {
// If the low bit is set, that means the value cannot
// be taken by reference
throw Exception("Collection values cannot be taken by reference", id);
}
Variant* ret = m_refs[id-1].var();
if (!ret) {
throw Exception("Collection keys cannot be taken by reference", id);
}
return ret;
}
int64_t readInt();
double readDouble();
char readChar() {
check();
return *(m_buf++);
}
void read(char *buf, uint n);
char peek() {
check();
return *m_buf;
}
const char *head() { return m_buf; }
Variant &addVar();
private:
struct RefInfo {
explicit RefInfo(Variant* v) : m_data(reinterpret_cast<uintptr_t>(v)) {}
static RefInfo makeNonRefable(Variant* v) {
RefInfo r(v);
r.m_data |= 1;
return r;
}
Variant* var() const {
return reinterpret_cast<Variant*>(m_data & ~1);
}
bool canBeReferenced() const { return !(m_data & 1); }
private:
uintptr_t m_data;
};
Type m_type;
const char *m_buf;
const char *m_end;
smart::vector<RefInfo> m_refs;
smart::list<Variant> m_vars;
bool m_unknownSerializable;
void check() {
if (m_buf >= m_end) {
throw Exception("Unexpected end of buffer during unserialization");
}
}
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // __HPHP_VARIABLE_UNSERIALIZER_H__