/* * * 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 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(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