blob: 9c577e6c92a81671595a986ac43ef95463dcc763 [file] [log] [blame]
/*
*
* 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