diff options
author | Kim van der Riet <kpvdr@apache.org> | 2013-02-28 16:14:30 +0000 |
---|---|---|
committer | Kim van der Riet <kpvdr@apache.org> | 2013-02-28 16:14:30 +0000 |
commit | 9c73ef7a5ac10acd6a50d5d52bd721fc2faa5919 (patch) | |
tree | 2a890e1df09e5b896a9b4168a7b22648f559a1f2 /cpp/src/qpid/amqp/Decoder.cpp | |
parent | 172d9b2a16cfb817bbe632d050acba7e31401cd2 (diff) | |
download | qpid-python-asyncstore.tar.gz |
Update from trunk r1375509 through r1450773asyncstore
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/asyncstore@1451244 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/amqp/Decoder.cpp')
-rw-r--r-- | cpp/src/qpid/amqp/Decoder.cpp | 545 |
1 files changed, 545 insertions, 0 deletions
diff --git a/cpp/src/qpid/amqp/Decoder.cpp b/cpp/src/qpid/amqp/Decoder.cpp new file mode 100644 index 0000000000..9c577e6c92 --- /dev/null +++ b/cpp/src/qpid/amqp/Decoder.cpp @@ -0,0 +1,545 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "qpid/amqp/Decoder.h" +#include "qpid/amqp/CharSequence.h" +#include "qpid/amqp/Constructor.h" +#include "qpid/amqp/Descriptor.h" +#include "qpid/amqp/Reader.h" +#include "qpid/amqp/typecodes.h" +#include "qpid/types/Uuid.h" +#include "qpid/types/Variant.h" +#include "qpid/log/Statement.h" +#include "qpid/Exception.h" + +namespace qpid { +namespace amqp { + +using namespace qpid::amqp::typecodes; + +Decoder::Decoder(const char* d, size_t s) : start(d), size(s), position(0) {} + +namespace { +class MapBuilder : public Reader +{ + public: + void onNull(const Descriptor*) + { + qpid::types::Variant v; + handle(v, NULL_NAME); + } + void onBoolean(bool v, const Descriptor*) + { + handle(v, BOOLEAN_NAME); + } + void onUByte(uint8_t v, const Descriptor*) + { + handle(v, UBYTE_NAME); + } + void onUShort(uint16_t v, const Descriptor*) + { + handle(v, USHORT_NAME); + } + void onUInt(uint32_t v, const Descriptor*) + { + handle(v, UINT_NAME); + } + void onULong(uint64_t v, const Descriptor*) + { + handle(v, ULONG_NAME); + } + void onByte(int8_t v, const Descriptor*) + { + handle(v, BYTE_NAME); + } + void onShort(int16_t v, const Descriptor*) + { + handle(v, SHORT_NAME); + } + void onInt(int32_t v, const Descriptor*) + { + handle(v, INT_NAME); + } + void onLong(int64_t v, const Descriptor*) + { + handle(v, LONG_NAME); + } + void onFloat(float v, const Descriptor*) + { + handle(v, FLOAT_NAME); + } + void onDouble(double v, const Descriptor*) + { + handle(v, DOUBLE_NAME); + } + void onUuid(const CharSequence& v, const Descriptor*) + { + handle(v, UUID_NAME); + } + void onTimestamp(int64_t v, const Descriptor*) + { + handle(v, TIMESTAMP_NAME); + } + void onBinary(const CharSequence& v, const Descriptor*) + { + handle(v); + } + void onString(const CharSequence& v, const Descriptor*) + { + handle(v); + } + void onSymbol(const CharSequence& v, const Descriptor*) + { + handle(v); + } + MapBuilder(qpid::types::Variant::Map& m) : map(m), state(KEY) {} + private: + qpid::types::Variant::Map& map; + enum {KEY, SKIP, VALUE} state; + std::string key; + + template <typename T> void handle(T value, const std::string& name) + { + switch (state) { + case KEY: + QPID_LOG(warning, "Ignoring key of type " << name); + state = SKIP; + break; + case VALUE: + map[key] = value; + case SKIP: + state = KEY; + break; + } + } + void handle(const CharSequence& value) + { + switch (state) { + case KEY: + key = value.str(); + state = VALUE; + break; + case VALUE: + map[key] = value.str(); + case SKIP: + state = KEY; + break; + } + } +}; +} +void Decoder::readMap(qpid::types::Variant::Map& map) +{ + MapBuilder builder(map); + read(builder); +} + +qpid::types::Variant::Map Decoder::readMap() +{ + qpid::types::Variant::Map map; + readMap(map); + return map; +} + +void Decoder::read(Reader& reader) +{ + while (available() && reader.proceed()) { + readOne(reader); + } +} + +void Decoder::readOne(Reader& reader) +{ + const char* temp = start + position; + Constructor c = readConstructor(); + if (c.isDescribed) reader.onDescriptor(c.descriptor, temp); + readValue(reader, c.code, c.isDescribed ? &c.descriptor : 0); +} + +void Decoder::readValue(Reader& reader, uint8_t code, const Descriptor* descriptor) +{ + switch(code) { + case NULL_VALUE: + reader.onNull(descriptor); + break; + case BOOLEAN: + reader.onBoolean(readBoolean(), descriptor); + break; + case BOOLEAN_TRUE: + reader.onBoolean(true, descriptor); + break; + case BOOLEAN_FALSE: + reader.onBoolean(false, descriptor); + break; + case UBYTE: + reader.onUByte(readUByte(), descriptor); + break; + case USHORT: + reader.onUShort(readUShort(), descriptor); + break; + case UINT: + reader.onUInt(readUInt(), descriptor); + break; + case UINT_SMALL: + reader.onUInt(readUByte(), descriptor); + break; + case UINT_ZERO: + reader.onUInt(0, descriptor); + break; + case ULONG: + reader.onULong(readULong(), descriptor); + break; + case ULONG_SMALL: + reader.onULong(readUByte(), descriptor); + break; + case ULONG_ZERO: + reader.onULong(0, descriptor); + break; + case BYTE: + reader.onByte(readByte(), descriptor); + break; + case SHORT: + reader.onShort(readShort(), descriptor); + break; + case INT: + reader.onInt(readInt(), descriptor); + break; + case INT_SMALL: + reader.onInt(readByte(), descriptor); + break; + case LONG: + reader.onLong(readLong(), descriptor); + break; + case LONG_SMALL: + reader.onLong(readByte(), descriptor); + break; + case FLOAT: + reader.onFloat(readFloat(), descriptor); + break; + case DOUBLE: + reader.onDouble(readDouble(), descriptor); + break; + case UUID: + reader.onUuid(readRawUuid(), descriptor); + break; + case TIMESTAMP: + reader.onTimestamp(readLong(), descriptor); + break; + + case BINARY8: + reader.onBinary(readSequence8(), descriptor); + break; + case BINARY32: + reader.onBinary(readSequence32(), descriptor); + break; + case STRING8: + reader.onString(readSequence8(), descriptor); + break; + case STRING32: + reader.onString(readSequence32(), descriptor); + break; + case SYMBOL8: + reader.onSymbol(readSequence8(), descriptor); + break; + case SYMBOL32: + reader.onSymbol(readSequence32(), descriptor); + break; + + case LIST0: + reader.onStartList(0, CharSequence::create(0, 0), descriptor); + reader.onEndList(0, descriptor); + break; + case LIST8: + readList8(reader, descriptor); + break; + case LIST32: + readList32(reader, descriptor); + break; + case MAP8: + readMap8(reader, descriptor); + break; + case MAP32: + readMap32(reader, descriptor); + break; + case ARRAY8: + readArray8(reader, descriptor); + break; + case ARRAY32: + readArray32(reader, descriptor); + break; + default: + break; + } +} + +void Decoder::readList8(Reader& reader, const Descriptor* descriptor) +{ + uint8_t size = readUByte(); + uint8_t count = readUByte(); + readList(reader, size-sizeof(size), count, descriptor); +} + +void Decoder::readList32(Reader& reader, const Descriptor* descriptor) +{ + uint32_t size = readUInt(); + uint32_t count = readUInt(); + readList(reader, size-sizeof(size), count, descriptor); +} + +void Decoder::readMap8(Reader& reader, const Descriptor* descriptor) +{ + uint8_t size = readUByte(); + uint8_t count = readUByte(); + readMap(reader, size-sizeof(size), count, descriptor); +} + +void Decoder::readMap32(Reader& reader, const Descriptor* descriptor) +{ + uint32_t size = readUInt(); + uint32_t count = readUInt(); + readMap(reader, size-sizeof(size), count, descriptor); +} + +void Decoder::readArray8(Reader& reader, const Descriptor* descriptor) +{ + uint8_t size = readUByte(); + uint8_t count = readUByte(); + readArray(reader, size-sizeof(size), count, descriptor); +} + +void Decoder::readArray32(Reader& reader, const Descriptor* descriptor) +{ + uint32_t size = readUInt(); + uint32_t count = readUInt(); + readArray(reader, size-sizeof(size), count, descriptor); +} + +void Decoder::readList(Reader& reader, uint32_t size, uint32_t count, const Descriptor* descriptor) +{ + if (reader.onStartList(count, CharSequence::create(data(), size), descriptor)) { + for (uint32_t i = 0; i < count; ++i) { + readOne(reader); + } + reader.onEndList(count, descriptor); + } else { + //skip + advance(size); + } +} +void Decoder::readMap(Reader& reader, uint32_t size, uint32_t count, const Descriptor* descriptor) +{ + if (reader.onStartMap(count, CharSequence::create(data(), size), descriptor)) { + for (uint32_t i = 0; i < count; ++i) { + readOne(reader); + } + reader.onEndMap(count, descriptor); + } else { + //skip + advance(size); + } +} + +void Decoder::readArray(Reader& reader, uint32_t size, uint32_t count, const Descriptor* descriptor) +{ + size_t temp = position; + Constructor constructor = readConstructor(); + CharSequence raw = CharSequence::create(data(), size-(position-temp)); + if (reader.onStartArray(count, raw, constructor, descriptor)) { + for (uint32_t i = 0; i < count; ++i) { + readValue(reader, constructor.code, constructor.isDescribed ? &constructor.descriptor : 0); + } + reader.onEndArray(count, descriptor); + } else { + //skip + advance(raw.size); + } +} + + +Constructor Decoder::readConstructor() +{ + Constructor result(readCode()); + if (result.code == DESCRIPTOR) { + result.isDescribed = true; + result.descriptor = readDescriptor(); + result.code = readCode(); + } else { + result.isDescribed = false; + } + return result; +} + +Descriptor Decoder::readDescriptor() +{ + uint8_t code = readCode(); + switch(code) { + case SYMBOL8: + return Descriptor(readSequence8()); + case SYMBOL32: + return Descriptor(readSequence32()); + case ULONG: + return Descriptor(readULong()); + case ULONG_SMALL: + return Descriptor((uint64_t) readUByte()); + case ULONG_ZERO: + return Descriptor((uint64_t) 0); + default: + throw qpid::Exception(QPID_MSG("Expected descriptor of type ulong or symbol; found " << code)); + } +} + +void Decoder::advance(size_t n) +{ + if (n > available()) throw qpid::Exception(QPID_MSG("Out of Bounds")); + position += n; +} + +const char* Decoder::data() +{ + return start + position; +} + +size_t Decoder::available() +{ + return size - position; +} + +uint8_t Decoder::readCode() +{ + return readUByte(); +} + +bool Decoder::readBoolean() +{ + return readUByte(); +} + +uint8_t Decoder::readUByte() +{ + return static_cast<uint8_t>(start[position++]); +} + +uint16_t Decoder::readUShort() +{ + uint16_t hi = (unsigned char) start[position++]; + hi = hi << 8; + hi |= (unsigned char) start[position++]; + return hi; +} + +uint32_t Decoder::readUInt() +{ + uint32_t a = (unsigned char) start[position++]; + uint32_t b = (unsigned char) start[position++]; + uint32_t c = (unsigned char) start[position++]; + uint32_t d = (unsigned char) start[position++]; + a = a << 24; + a |= b << 16; + a |= c << 8; + a |= d; + return a; +} + +uint64_t Decoder::readULong() +{ + uint64_t hi =readUInt(); + uint64_t lo = readUInt(); + hi = hi << 32; + return hi | lo; +} + +int8_t Decoder::readByte() +{ + return (int8_t) readUByte(); +} + +int16_t Decoder::readShort() +{ + return (int16_t) readUShort(); +} + +int32_t Decoder::readInt() +{ + return (int32_t) readUInt(); +} + +int64_t Decoder::readLong() +{ + return (int64_t) readULong(); +} + +float Decoder::readFloat() +{ + union { + uint32_t i; + float f; + } val; + val.i = readUInt(); + return val.f; +} + +double Decoder::readDouble() +{ + union { + uint64_t i; + double f; + } val; + val.i = readULong(); + return val.f; +} + +CharSequence Decoder::readSequence8() +{ + CharSequence s; + s.size = readUByte(); + s.data = start + position; + advance(s.size); + return s; +} + +CharSequence Decoder::readSequence32() +{ + CharSequence s; + s.size = readUInt(); + s.data = start + position; + advance(s.size); + return s; +} + +qpid::types::Uuid Decoder::readUuid() +{ + qpid::types::Uuid uuid(start + position); + advance(16); + return uuid; +} + +CharSequence Decoder::readRawUuid() +{ + CharSequence s; + s.data = start + position; + s.size = 16; + advance(s.size); + return s; +} + +size_t Decoder::getPosition() const { return position; } +size_t Decoder::getSize() const { return size; } +void Decoder::resetSize(size_t s) { size = s; } +}} // namespace qpid::amqp |