Skip to content

Commit

Permalink
Implemented preliminary interface & buffer management
Browse files Browse the repository at this point in the history
  • Loading branch information
luvies committed Apr 5, 2019
1 parent 2da766e commit 9ef4367
Show file tree
Hide file tree
Showing 3 changed files with 220 additions and 37 deletions.
106 changes: 93 additions & 13 deletions src/serializer/array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "./document.hpp"
#include "./result.hpp"
#include "stdio.h"
#include "stdlib.h"

namespace pot {
Expand All @@ -11,26 +12,105 @@ namespace serializer {

class Array {
public:
Array(uint8_t *buf, uint32_t len) : doc_(buf, len) {}
Array(Document *parent) : doc_(parent) {}
Array(Document &parent) : doc_(parent) {}

~Array() {
end();
Array &append(double value) {
char key[12];
handleIndex(key);
doc_.append(key, value);

return *this;
}

Result append(double value);
Result append(const char str[]);
Result append(uint8_t buf[]);
Result append(bool value);
Result append();
Result append(uint32_t value);
Result append(uint64_t value);
Array &append(const char str[]) {
char key[12];
handleIndex(key);
doc_.append(key, str);

return *this;
}

Array &append(void (*builder)(Document)) {
char key[12];
handleIndex(key);
doc_.append(key, builder);

return *this;
}

Array &append(void (*builder)(Array)) {
char key[12];
handleIndex(key);
doc_.append(key, builder);

return *this;
}

Result end();
Array &append(uint8_t buf[], size_t len) {
char key[12];
handleIndex(key);
doc_.append(key, buf, len);

return *this;
}

Array &append(bool value) {
char key[12];
handleIndex(key);
doc_.append(key, value);

return *this;
}

Array &append() {
char key[12];
handleIndex(key);
doc_.append(key);

return *this;
}

Array &append(uint32_t value) {
char key[12];
handleIndex(key);
doc_.append(key, value);

return *this;
}

Array &append(uint64_t value) {
char key[12];
handleIndex(key);
doc_.append(key, value);

return *this;
}

Result end() {
return doc_.end();
}

void syncWith(Document &child) {
doc_.syncWith(child);
}

void syncWith(Array &child) {
doc_.syncWith(child);
}

void syncTo(Document &parent) {
parent.syncWith(doc_);
}

private:
Document doc_;
uint32_t index_ = 0;
size_t index_ = 0;

int handleIndex(char key[]) {
int ret = snprintf(key, sizeof(key), "%Lu", index_);
index_++;
return ret;
}
};

} // namespace serializer
Expand Down
124 changes: 107 additions & 17 deletions src/serializer/document.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef POT_BSON_SERIALIZER_DOCUMENT_H_
#define POT_BSON_SERIALIZER_DOCUMENT_H_

#include "../consts.hpp"
#include "./array.hpp"
#include "./result.hpp"
#include "stdlib.h"

Expand All @@ -10,33 +12,121 @@ namespace serializer {

class Document {
public:
Document(uint8_t buf[], uint32_t len) : buffer_(buf), buffer_length_(len) {}
Document(Document *parent) :
buffer_(parent->buffer_), buffer_length_(parent->buffer_length_), current_(parent->current_),
parent_(parent) {}
Document(uint8_t buf[], size_t len) : buffer_(buf), buffer_length_(len) {
start();
}
Document(Document &parent) :
buffer_(parent.buffer_), buffer_length_(parent.buffer_length_), current_(parent.current_),
start_(parent.start_) {
start();
}

Document &append(const char key[], double value);

Document &append(const char key[], const char str[]);

Document &append(const char key[], void (*builder)(Document)) {
Document child(*this);
builder(child);
syncWith(child);

return *this;
}

Document &append(const char key[], void (*builder)(Array)) {
Array child(*this);
builder(child);
syncWith(child);

return *this;
}

Document &append(const char key[], uint8_t buf[], size_t len);

Document &append(const char key[], bool value);

Document &append(const char key[]);

Document &append(const char key[], uint32_t value);

Document &append(const char key[], uint64_t value);

~Document() {
end();
Result end() {
uint8_t endByte = 0x00;
write(&endByte, 1);

uint32_t len = current_ - start_;

// Attempt to write length of the document into the start.
if (start_ < buffer_length_) {
buffer_[start_] = len;
}

Result res;
res.len = len;
if (current_ <= buffer_length_) {
res.status = Status::Ok;
} else {
res.status = Status::BufferOverflow;
}

return res;
}

Result append(const char key[], double value);
Result append(const char key[], const char str[]);
Result append(const char key[], uint8_t buf[]);
Result append(const char key[], bool value);
Result append(const char key[]);
Result append(const char key[], uint32_t value);
Result append(const char key[], uint64_t value);
void syncWith(Document &child) {
current_ = child.current_;
}

Result end();
void syncWith(Array &child) {
child.syncTo(*this);
}

private:
uint8_t *buffer_;
uint32_t buffer_length_;
size_t buffer_length_;
uint32_t current_ = 0;
Document *parent_ = nullptr;
uint32_t start_ = 0;
bool ended_ = false;

bool start();
void start() {
if (current_ < buffer_length_) {
// The document is currently 0 bytes long.
buffer_[current_] = 0x00;
}
current_++;
}

void write(Element type, const char key[], uint8_t buf[], size_t len) {
if (current_ < buffer_length_) {
buffer_[current_] = (uint8_t)type;
}
current_++;

uint32_t key_char = 0;
while (true) {
char chr = key[key_char];

if (chr == '\0') {
break;
}

if (current_ < buffer_length_) {
buffer_[current_] = chr;
}
current_++;
}

write(buf, len);
}

void write(uint8_t buf[], size_t len) {
for (uint32_t i = 0; i < len; i++) {
if (current_ < buffer_length_) {
buffer_[current_] = buf[i];
}
current_++;
}
}
};

} // namespace serializer
Expand Down
27 changes: 20 additions & 7 deletions src/serializer/result.hpp
Original file line number Diff line number Diff line change
@@ -1,26 +1,39 @@
#ifndef POT_BSON_SERIALIZER_RESULT_H_
#define POT_BSON_SERIALIZER_RESULT_H_

#include "stdlib.h"

namespace pot {
namespace bson {
namespace serializer {

enum struct Result {
struct Result {
/**
* The resulting status code from the attempted action.
*/
Status status;
/**
* This is the total length of the document. Even if there was a buffer
* overflow, this will still be accurate, and can be used to reallocate
* a buffer of the required size if necessary.
*/
size_t len;
};

enum struct Status {
/**
* The operation completed without errors.
*/
Ok,
/**
* The requested operation would have overflowed the buffer.
* The document couldn't be completed because it would have overflowed the buffer.
* If this is returned, then the buffer is assumed to be in an invalid state,
* and the document will have to be reconstructed from the beginning.
*/
BufferOverflow,
/**
* The document has already been ended, and no more operations are allowed.
*/
Ended,
};

}
} // namespace serializer
} // namespace bson
} // namespace pot

Expand Down

0 comments on commit 9ef4367

Please sign in to comment.