Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
voivoid committed Apr 2, 2017
1 parent 197f4fe commit da4c780
Show file tree
Hide file tree
Showing 10 changed files with 381 additions and 0 deletions.
36 changes: 36 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 3.8)
project(BsonParser LANGUAGES CXX)

add_library(BsonParser STATIC
inc/Bson/Details/common.h
inc/Bson/parser.h
src/parser.cpp
inc/Bson/Details/utils.h
src/utils.cpp
)

target_include_directories(BsonParser PUBLIC inc)

if(NOT MSVC)
target_compile_options(BsonParser PUBLIC -Wall -Wextra -Werror -std=c++14)
endif()

enable_testing()

add_executable(BsonParserTestUtils test/test-utils.cpp)
target_link_libraries(BsonParserTestUtils PRIVATE BsonParser)

add_executable(BsonParserTestEncode test/test-encode.cpp)
target_link_libraries(BsonParserTestEncode PRIVATE BsonParser)

add_executable(BsonParserTestDecode test/test-decode.cpp)
target_link_libraries(BsonParserTestDecode PRIVATE BsonParser)

add_executable(BsonParserTestEncodeDecode test/test-encode-decode.cpp)
target_link_libraries(BsonParserTestEncodeDecode PRIVATE BsonParser)

add_test(NAME BsonParserUtils COMMAND BsonParserTestUtils)
add_test(NAME BsonParserEncode COMMAND BsonParserTestDecode)
add_test(NAME BsonParserDecode COMMAND BsonParserTestEncode)
add_test(NAME BsonParserEncodeDecode COMMAND BsonParserTestEncodeDecode)

26 changes: 26 additions & 0 deletions inc/BSON/Details/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <vector>
#include <iterator>

namespace Bson
{

using Byte = unsigned char;
using Int32 = std::int32_t;
using Int64 = std::int64_t;
using Uint64 = std::uint64_t;
using Double = double;

#ifdef __GNUC__
using Decimal = __float128;
#else
#error "Unsupported platform"
#endif

using Bytes = std::vector<Byte>;

using Istream = std::basic_istream<Byte>;
using Ostream = std::basic_ostream<Byte>;

} // namespace Bson
36 changes: 36 additions & 0 deletions inc/BSON/Details/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#pragma once

#include "Bson/Details/common.h"
#include <cstdint>
#include <string>
#include <vector>
#include <boost/variant.hpp>

namespace Bson
{

template <typename T>
T read(Istream& stream);

template <typename T>
void write(T value, Ostream& stream);

std::string readCString(Istream& stream);
std::string readString(Istream& stream);

void writeCString(const std::string& string, Ostream& stream);
void writeString(const std::string& string, Ostream& stream);

struct True {};
struct False {};

using Element = boost::variant<Double, std::string, False, True, Int32, Uint64, Int64, Uint64, Decimal>;
Element readElement(Istream& stream);
void writeElement(const Element& element, Ostream& stream);

using List = std::vector<Element>;
List readList(Istream& stream);
void writeList(const List& list, Ostream& stream);


} // namespace Bson
22 changes: 22 additions & 0 deletions inc/BSON/parser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "Bson/Details/common.h"
#include "Bson/Details/utils.h"

#include <string>

namespace Bson
{

class Document
{
public:

private:
List _list;
};

Bytes encode(const Document&);
Document decode(const Bytes&);

} // namespace Bson
17 changes: 17 additions & 0 deletions src/parser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "BSON/parser.h"

namespace Bson
{

std::vector<Byte> encode(const Document&)
{
return {};
}

Document decode(const std::vector<Byte>&)
{
return {};
}


} // namespace Bson
96 changes: 96 additions & 0 deletions src/utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include "BSON/Details/utils.h"

#include <algorithm>
#include <cassert>
#include <limits>

#include <boost\bimap\bimap.hpp>

namespace Bson
{

const size_t MaxCStringBuff = 16384;

//enum class ElementType {
// Double = 0x01,
// String = 0x02,
// Int32 = 0x10,
// Uint32 = 0x10,
// Int64 = 0x12,
// Decimal = 0x13
//};
//const boost::bimaps::bimap<int, ElementType> ElementTypes = {};

// TODO: handle endianness

template <typename T>
T read(Istream& stream)
{
T value;
stream.read(reinterpret_cast<Byte*>(&value), sizeof(value));
return value;
}

template <typename T>
void write(const T value, Ostream& stream)
{
stream.write(reinterpret_cast<const Byte*>(&value), sizeof(value));
}

#define BSON_INSTANTIATE_FUNCS(type) \
template type read(Istream& iter); \
template void write(const type value, Ostream& iter); \

BSON_INSTANTIATE_FUNCS(Byte);
BSON_INSTANTIATE_FUNCS(Int32);
BSON_INSTANTIATE_FUNCS(Int64);
BSON_INSTANTIATE_FUNCS(Uint64);
BSON_INSTANTIATE_FUNCS(Double);
BSON_INSTANTIATE_FUNCS(Decimal);

std::string readCString(Istream& stream)
{
Byte buff[MaxCStringBuff];
stream.getline(buff, MaxCStringBuff, 0);

return std::string(reinterpret_cast<char*>(buff));
}

std::string readString(Istream& stream)
{
Int32 strLen = read<Int32>(stream);

assert(strLen > 0);

std::string s;
s.resize(strLen - 1);
stream.read(reinterpret_cast<Byte*>(&s[0]), strLen - 1);
stream.ignore(1);

return s;
}

void writeCString(const std::string& string, Ostream& stream)
{
stream.write(reinterpret_cast<const Byte*>(string.c_str()), string.length() + 1);
}

void writeString(const std::string& string, Ostream& stream)
{
write(static_cast<Int32>(string.length() + 1), stream);
writeCString(string, stream);
}

Element readElement(Istream& stream)
{
const auto elementType = read<Byte>(stream);

return {};
}

void writeElement(const Element& element, Ostream& stream)
{

}

} // namespace Bson
9 changes: 9 additions & 0 deletions test/test-decode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "Bson/parser.h"

int main() {

const auto input = Bson::Bytes{0x16,0x00,0x00,0x00,0x02,'h','e','l','l','o',0x00,0x06,0x00,0x00,0x00,'w','o','r','l','d',0x00,0x00};
Bson::decode(input);

return 0;
}
13 changes: 13 additions & 0 deletions test/test-encode-decode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "Bson/parser.h"

#include <string>
#include <cassert>

int main() {

const auto input = Bson::Bytes{0x16,0x00,0x00,0x00,0x02,'h','e','l','l','o',0x00,0x06,0x00,0x00,0x00,'w','o','r','l','d',0x00,0x00};
const auto result = Bson::encode(Bson::decode(input));
const auto expected = input;

return result == expected ? 0 : 1;
}
12 changes: 12 additions & 0 deletions test/test-encode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "Bson/parser.h"

#include <string>
#include <cassert>

int main() {

Bson::Document doc;
Bson::encode(doc);

return 0;
}
114 changes: 114 additions & 0 deletions test/test-utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include "Bson/Details/utils.h"

#include <cassert>
#include <sstream>
#include <iterator>
#include <limits>
#include <iostream>
#include <string>
#include <vector>

#include <boost\iostreams\device\array.hpp>
#include <boost\iostreams\stream.hpp>

template <typename T, typename WriteFunc, typename ReadFunc>
bool testMemory(const T& value, size_t buffSize, WriteFunc write, ReadFunc read)
{
std::vector<Bson::Byte> data(buffSize, 0);

boost::iostreams::basic_array<Bson::Byte> arr(data.data(), data.size());
boost::iostreams::stream<boost::iostreams::basic_array<Bson::Byte>> istream(arr);
boost::iostreams::stream<boost::iostreams::basic_array<Bson::Byte>> ostream(arr);

write(value, ostream);
const auto result = read(istream);

return result == value;
}

template <typename T, typename WriteFunc, typename ReadFunc>
bool testStream(T val, WriteFunc write, ReadFunc read)
{
std::basic_stringstream<Bson::Byte> ss(std::ios_base::in | std::ios_base::out | std::ios_base::binary);
write(val, ss);
const auto result = read(ss);

return val == result;
}

template <typename T>
void test(T value)
{
assert(testMemory(value, sizeof(value), Bson::write<T>, Bson::read<T>));
assert(testStream(value, Bson::write<T>, Bson::read<T>));
}

void testString(const std::string& value)
{
assert(testMemory(value, value.length() + sizeof(Bson::Int32) + 1, Bson::writeString, Bson::readString));
assert(testStream(value, Bson::writeString, Bson::readString));
}

void test(const std::string& value)
{
assert(testMemory(value, value.length() + 1, Bson::writeCString, Bson::readCString));
assert(testStream(value, Bson::writeCString, Bson::readCString));
testString(value);
}

int main() {

test<Bson::Byte>(0);
test<Bson::Byte>(1);
test<Bson::Byte>(42);
test<Bson::Byte>(255);

test<Bson::Int32>(0);
test<Bson::Int32>(1);
test<Bson::Int32>(-1);
test<Bson::Int32>(42);
test<Bson::Int32>(-42);
test<Bson::Int32>(0x01020304);
test<Bson::Int32>(0xff0000ff);
test<Bson::Int32>(std::numeric_limits<Bson::Int32>::min());
test<Bson::Int32>(std::numeric_limits<Bson::Int32>::max());

test<Bson::Int64>(0);
test<Bson::Int64>(1);
test<Bson::Int64>(-1);
test<Bson::Int64>(42);
test<Bson::Int64>(-42);
test<Bson::Int64>(0x01020304);
test<Bson::Int64>(std::numeric_limits<Bson::Int64>::min());
test<Bson::Int64>(std::numeric_limits<Bson::Int64>::max());

test<Bson::Uint64>(0);
test<Bson::Uint64>(1);
test<Bson::Uint64>(42);
test<Bson::Uint64>(0x01020304);
test<Bson::Uint64>(std::numeric_limits<Bson::Uint64>::min());
test<Bson::Uint64>(std::numeric_limits<Bson::Uint64>::max());

test<Bson::Double>(0.0);
test<Bson::Double>(0.1);
test<Bson::Double>(0.-1);
test<Bson::Double>(1.0);
test<Bson::Double>(-1.0);
test<Bson::Double>(std::numeric_limits<Bson::Double>::min());
test<Bson::Double>(std::numeric_limits<Bson::Double>::max());

test<Bson::Decimal>(0.0);
test<Bson::Decimal>(0.1);
test<Bson::Decimal>(0.-1);
test<Bson::Decimal>(1.0);
test<Bson::Decimal>(-1.0);
test<Bson::Decimal>(std::numeric_limits<Bson::Decimal>::min());
test<Bson::Decimal>(std::numeric_limits<Bson::Decimal>::max());

test(std::string(""));
test(std::string("hello"));
test(std::string("hello world"));
testString(std::string("hello\0world", 11));

return 0;
}

0 comments on commit da4c780

Please sign in to comment.