amf.h 5.56 KB
Newer Older
xiongziliang committed
1
/*
xiongziliang committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 * MIT License
 *
 * Copyright (c) 2016 xiongziliang <771730766@qq.com>
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
xzl committed
26 27 28 29
#ifndef __amf_h
#define __amf_h

#include <assert.h>
xiongzilaing committed
30
#include <string>
xzl committed
31
#include <vector>
xiongzilaing committed
32
#include <unordered_map>
xiongziliang committed
33
#include <map>
xzl committed
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
enum AMFType {
	AMF_NUMBER,
	AMF_INTEGER,
	AMF_BOOLEAN,
	AMF_STRING,
	AMF_OBJECT,
	AMF_NULL,
	AMF_UNDEFINED,
	AMF_ECMA_ARRAY,
	AMF_STRICT_ARRAY,
};

class AMFValue;

class AMFValue {
public:

	AMFValue(AMFType type = AMF_NULL);
	AMFValue(const char *s);
	AMFValue(const std::string &s);
	AMFValue(double n);
	AMFValue(int i);
	AMFValue(bool b);
	AMFValue(const AMFValue &from);
	AMFValue(AMFValue &&from);
	AMFValue &operator =(const AMFValue &from);
	AMFValue &operator =(AMFValue &&from);
	~AMFValue();

	void clear() {
64
		switch (_type) {
xzl committed
65
		case AMF_STRING:
66
			_value.string->clear();
xzl committed
67 68 69
			break;
		case AMF_OBJECT:
		case AMF_ECMA_ARRAY:
70
			_value.object->clear();
xzl committed
71 72 73 74 75 76 77
			break;
		default:
			break;
		}
	}

	AMFType type() const {
78
		return _type;
xzl committed
79 80 81
	}

	const std::string &as_string() const {
82
		if(_type != AMF_STRING){
xzl committed
83 84
			throw std::runtime_error("AMF not a string");
		}
85
		return *_value.string;
xzl committed
86 87
	}
	double as_number() const {
88
		switch (_type) {
xzl committed
89
		case AMF_NUMBER:
90
			return _value.number;
xzl committed
91
		case AMF_INTEGER:
92
			return _value.integer;
xzl committed
93
		case AMF_BOOLEAN:
94
			return _value.boolean;
xzl committed
95 96 97 98 99 100 101
			break;
		default:
			throw std::runtime_error("AMF not a number");
			break;
		}
	}
	int as_integer() const {
102
		switch (_type) {
xzl committed
103
		case AMF_NUMBER:
104
			return _value.number;
xzl committed
105
		case AMF_INTEGER:
106
			return _value.integer;
xzl committed
107
		case AMF_BOOLEAN:
108
			return _value.boolean;
xzl committed
109 110 111 112 113 114 115
			break;
		default:
			throw std::runtime_error("AMF not a integer");
			break;
		}
	}
	bool as_boolean() const {
116
		switch (_type) {
xzl committed
117
		case AMF_NUMBER:
118
			return _value.number;
xzl committed
119
		case AMF_INTEGER:
120
			return _value.integer;
xzl committed
121
		case AMF_BOOLEAN:
122
			return _value.boolean;
xzl committed
123 124 125 126 127 128 129
			break;
		default:
			throw std::runtime_error("AMF not a boolean");
			break;
		}
	}

xiongziliang committed
130
	const AMFValue &operator[](const char *str) const {
131
		if (_type != AMF_OBJECT && _type != AMF_ECMA_ARRAY) {
xzl committed
132 133
			throw std::runtime_error("AMF not a object");
		}
134 135
		auto i = _value.object->find(str);
		if (i == _value.object->end()) {
xzl committed
136 137 138 139 140 141 142
			static AMFValue val(AMF_NULL);
			return val;
		}
		return i->second;
	}
	template<typename FUN>
	void object_for_each(const FUN &fun) const {
143
		if (_type != AMF_OBJECT && _type != AMF_ECMA_ARRAY) {
xzl committed
144 145
			throw std::runtime_error("AMF not a object");
		}
146
		for (auto & pr : *(_value.object)) {
xzl committed
147 148 149 150
			fun(pr.first, pr.second);
		}
	}

xiongziliang committed
151
	operator bool() const{
152
		return _type != AMF_NULL;
xzl committed
153 154
	}
	void set(const std::string &s, const AMFValue &val) {
155
		if (_type != AMF_OBJECT && _type != AMF_ECMA_ARRAY) {
xzl committed
156 157
			throw std::runtime_error("AMF not a object");
		}
158
		_value.object->emplace(s, val);
xzl committed
159 160
	}
	void add(const AMFValue &val) {
161
		if (_type != AMF_STRICT_ARRAY) {
xzl committed
162 163
			throw std::runtime_error("AMF not a array");
		}
164 165
		assert(_type == AMF_STRICT_ARRAY);
		_value.array->push_back(val);
xzl committed
166 167 168
	}

private:
xiongziliang committed
169
	typedef std::map<std::string, AMFValue> mapType;
xzl committed
170 171
	typedef std::vector<AMFValue> arrayType;

172
	AMFType _type;
xzl committed
173 174 175 176 177 178 179
	union {
		std::string *string;
		double number;
		int integer;
		bool boolean;
		mapType *object;
		arrayType *array;
180
	} _value;
xzl committed
181 182 183

	friend class AMFEncoder;
	const mapType &getMap() const {
184
		if (_type != AMF_OBJECT && _type != AMF_ECMA_ARRAY) {
xzl committed
185 186
			throw std::runtime_error("AMF not a object");
		}
187
		return *_value.object;
xzl committed
188 189
	}
	const arrayType &getArr() const {
190
		if (_type != AMF_STRICT_ARRAY) {
xzl committed
191 192
			throw std::runtime_error("AMF not a array");
		}
193
		return *_value.array;
xzl committed
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
	}
	inline void destroy();
	inline void init();
};

class AMFDecoder {
public:
	AMFDecoder(const std::string &_buf, size_t _pos, int _version = 0) :
			buf(_buf), pos(_pos), version(_version) {
	}

	int getVersion() const {
		return version;
	}

	template<typename TP>
	TP load();



private:
	const std::string &buf;
	size_t pos;
	int version;

	std::string load_key();
	AMFValue load_object();
	AMFValue load_ecma();
	AMFValue load_arr();
	uint8_t front();
	uint8_t pop_front();
};

class AMFEncoder {
public:
	AMFEncoder & operator <<(const char *s);
	AMFEncoder & operator <<(const std::string &s);
	AMFEncoder & operator <<(std::nullptr_t);
	AMFEncoder & operator <<(const int n);
	AMFEncoder & operator <<(const double n);
	AMFEncoder & operator <<(const bool b);
	AMFEncoder & operator <<(const AMFValue &value);
	const std::string data() const {
		return buf;
	}
	void clear() {
		buf.clear();
	}
private:
	void write_key(const std::string &s);
	AMFEncoder &write_undefined();
	std::string buf;
};


#endif