First commit
This commit is contained in:
commit
35beaf4b73
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*.d
|
||||||
|
*.o
|
||||||
|
*.mst
|
500
MStorage.cpp
Normal file
500
MStorage.cpp
Normal file
@ -0,0 +1,500 @@
|
|||||||
|
#include "MStorage.h"
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
MStorageInt32::MStorageInt32(int32_t val) { this->val = val; }
|
||||||
|
|
||||||
|
MStorageDataType MStorageInt32::getType() { return MDT_INT32; }
|
||||||
|
|
||||||
|
uint8_t MStorageInt32::getByte() { return val & 0xFF; }
|
||||||
|
|
||||||
|
double MStorageInt32::getDouble() { return (double)val; }
|
||||||
|
|
||||||
|
int32_t MStorageInt32::getInt() { return val; }
|
||||||
|
|
||||||
|
void MStorageInt32::writeData(std::ostream &of) {
|
||||||
|
of.put((char)getType());
|
||||||
|
of.write((char*)&val , sizeof(int32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorageInt32::readData(std::istream &ifs) {
|
||||||
|
ifs.read((char*)&val, sizeof(int32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t MStorageInt32::getLength(){
|
||||||
|
return sizeof(int32_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
MStorageDouble::MStorageDouble(double val) { this->val = val; }
|
||||||
|
|
||||||
|
MStorageDataType MStorageDouble::getType() { return MDT_DOUBLE; }
|
||||||
|
|
||||||
|
uint8_t MStorageDouble::getByte() { return ((int32_t)val) & 0xFF; }
|
||||||
|
|
||||||
|
double MStorageDouble::getDouble() { return val; }
|
||||||
|
|
||||||
|
int32_t MStorageDouble::getInt() { return (int32_t)val; }
|
||||||
|
|
||||||
|
void MStorageDouble::writeData(std::ostream &of) {
|
||||||
|
of.put((char)getType());
|
||||||
|
of.write((char*)&val , sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorageDouble::readData(std::istream &ifs) {
|
||||||
|
ifs.read((char*)&val, sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t MStorageDouble::getLength(){
|
||||||
|
return sizeof(double);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
MStorageByte::MStorageByte(int8_t val) { this->val = val; }
|
||||||
|
|
||||||
|
MStorageDataType MStorageByte::getType() { return MDT_BYTE; }
|
||||||
|
|
||||||
|
uint8_t MStorageByte::getByte() { return val; }
|
||||||
|
|
||||||
|
double MStorageByte::getDouble() { return (double) val; }
|
||||||
|
|
||||||
|
int32_t MStorageByte::getInt() { return (int32_t) val; }
|
||||||
|
|
||||||
|
void MStorageByte::writeData(std::ostream &of) {
|
||||||
|
of.put((char)getType());
|
||||||
|
of.put((char)val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorageByte::readData(std::istream &ifs) {
|
||||||
|
ifs.read((char*)&val, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t MStorageByte::getLength(){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
MStorageString::MStorageString(std::string val) {
|
||||||
|
this->val = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
MStorageDataType MStorageString::getType() {
|
||||||
|
return MDT_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MStorageString::getString() {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorageString::writeData(std::ostream &of) {
|
||||||
|
of.put((char)getType());
|
||||||
|
uint16_t slen = val.size();
|
||||||
|
of.write((char*)&slen, sizeof(uint16_t));
|
||||||
|
for(size_t pos = 0; pos < slen; ++pos) {
|
||||||
|
of << val.at(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorageString::readData(std::istream &ifs) {
|
||||||
|
uint16_t slen;
|
||||||
|
ifs.read((char*)&slen, sizeof(uint16_t));
|
||||||
|
char* str = new char[slen];
|
||||||
|
ifs.read(str, slen);
|
||||||
|
val = std::string(str, slen);
|
||||||
|
delete[] str;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t MStorageString::getLength(){
|
||||||
|
return val.size() + sizeof(uint16_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
MStorageInt32Array::MStorageInt32Array(int32_t *data, uint16_t len){
|
||||||
|
if(!data || len == 0){
|
||||||
|
val_len = 0;
|
||||||
|
val = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
val_len = len;
|
||||||
|
val = new int32_t[val_len];
|
||||||
|
memcpy(val, data, sizeof(uint32_t) * val_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
MStorageInt32Array::~MStorageInt32Array(){
|
||||||
|
delete[] val;
|
||||||
|
}
|
||||||
|
|
||||||
|
MStorageDataType MStorageInt32Array::getType(){
|
||||||
|
return MDT_INT32_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t *MStorageInt32Array::getIntArray(){
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t MStorageInt32Array::getLength(){
|
||||||
|
return sizeof(int32_t) * val_len + sizeof(uint16_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t MStorageInt32Array::getArrayLength(){
|
||||||
|
return val_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorageInt32Array::writeData(std::ostream &of){
|
||||||
|
of.put((char)getType());
|
||||||
|
of.write((char*)&val_len, sizeof(uint16_t));
|
||||||
|
for(size_t pos = 0; pos < val_len; ++pos) {
|
||||||
|
of.write((char*)&val[pos] , sizeof(int32_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorageInt32Array::readData(std::istream &ifs){
|
||||||
|
if(val)
|
||||||
|
delete[] val;
|
||||||
|
|
||||||
|
ifs.read((char*)&val_len, sizeof(uint16_t));
|
||||||
|
val = new int32_t[val_len];
|
||||||
|
ifs.read((char*)val, sizeof(int32_t) * val_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
MStorage::MStorage() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MStorage::~MStorage() {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t MStorage::writeToFile(std::string fname) {
|
||||||
|
std::ofstream of;
|
||||||
|
of.open(fname.c_str(), std::ios::binary | std::ios::out);
|
||||||
|
if(!of.is_open()) {
|
||||||
|
fprintf(stderr, "MStorage::%s(): Unable to open %s for writing!\n", __FUNCTION__, fname.c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
of.write((char*)_mst_header, MST_HEADER_LEN);
|
||||||
|
writeData(of);
|
||||||
|
of.close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t MStorage::readFromFile(std::string fname){
|
||||||
|
std::ifstream ifs;
|
||||||
|
unsigned char mst_header[MST_HEADER_LEN];
|
||||||
|
|
||||||
|
ifs.open(fname.c_str(), std::ios::binary | std::ios::in);
|
||||||
|
if(!ifs.is_open()) {
|
||||||
|
fprintf(stderr, "MStorage::%s(): Unable to open %s for reading!\n", __FUNCTION__, fname.c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ifs.read((char*)mst_header, MST_HEADER_LEN);
|
||||||
|
|
||||||
|
if (memcmp(mst_header, _mst_header, MST_HEADER_LEN) != 0) {
|
||||||
|
fprintf(stderr, "MStorage::%s(): File header is wrong!\n", __FUNCTION__);
|
||||||
|
ifs.close();
|
||||||
|
return 2;
|
||||||
|
} else {
|
||||||
|
values.clear();
|
||||||
|
uint8_t selfDtype = 0;
|
||||||
|
ifs.read((char*)&selfDtype, 1);
|
||||||
|
if(selfDtype != MDT_GROUP){
|
||||||
|
fprintf(stderr, "MStorage::%s(): Wrong group data type"
|
||||||
|
"(0x%02x)!\n", __FUNCTION__, selfDtype);
|
||||||
|
ifs.close();
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
readData(ifs);
|
||||||
|
ifs.close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ifs.close();
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorage::insertRaw(const std::string &key, IMStorageBase *val){
|
||||||
|
size_t klen = key.size();
|
||||||
|
if(klen > 0xFF) {
|
||||||
|
fprintf(stderr, "MStorage::%s(): Key name is too long (%u), skipping\n", __FUNCTION__, klen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MValueMapIterator it = values.find(key);
|
||||||
|
if(it == end()) {
|
||||||
|
values[key] = val;
|
||||||
|
} else { // replacing
|
||||||
|
if(it->second)
|
||||||
|
delete it->second;
|
||||||
|
it->second = val;
|
||||||
|
// fprintf(stderr, "MStorage::%s(): Value with key \"%s\" is already exists!\n",
|
||||||
|
// __FUNCTION__, key.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IMStorageBase *MStorage::getRaw(const std::string &key){
|
||||||
|
if(values.find(key) == end()) {
|
||||||
|
fprintf(stderr, "MStorage::%s(): Value with key \"%s\" not found!\n",
|
||||||
|
__FUNCTION__, key.c_str());
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
return values[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorage::setInt(const std::string &key, uint32_t val) {
|
||||||
|
insertRaw(key, new MStorageInt32(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorage::setIntArray(const std::string &key, int32_t *val, uint16_t len)
|
||||||
|
{
|
||||||
|
insertRaw(key, new MStorageInt32Array(val, len));
|
||||||
|
}
|
||||||
|
void MStorage::setByteArray(const std::string &key, uint8_t *val, uint16_t len)
|
||||||
|
{
|
||||||
|
insertRaw(key, new MStorageByteArray(val, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorage::setDouble(const std::string &key, double val) {
|
||||||
|
insertRaw(key, new MStorageDouble(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorage::setByte(const std::string &key, uint8_t val) {
|
||||||
|
insertRaw(key, new MStorageByte(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorage::setString(const std::string &key, std::string val) {
|
||||||
|
insertRaw(key, new MStorageString(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorage::setGroup(const std::string &key, MStorage *group)
|
||||||
|
{
|
||||||
|
insertRaw(key, group);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t MStorage::getInt(const std::string &key) {
|
||||||
|
IMStorageBasicType *bval = getBasicType(key);
|
||||||
|
return bval ? bval->getInt() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t *MStorage::getIntArray(const std::string &key, uint16_t *len)
|
||||||
|
{
|
||||||
|
IMStorageBase *bval = getRaw(key);
|
||||||
|
if(!bval){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(bval->getType() != MDT_INT32_ARRAY) {
|
||||||
|
fprintf(stderr, "MStorage::%s(): Value is not INT32 ARRAY!\n", __FUNCTION__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MStorageInt32Array *sval = static_cast<MStorageInt32Array*>(bval);
|
||||||
|
if(len)
|
||||||
|
*len = sval->getArrayLength();
|
||||||
|
return sval->getIntArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *MStorage::getByteArray(const std::string &key, uint16_t *len)
|
||||||
|
{
|
||||||
|
IMStorageBase *bval = getRaw(key);
|
||||||
|
if(!bval){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(bval->getType() != MDT_BYTE_ARRAY) {
|
||||||
|
fprintf(stderr, "MStorage::%s(): Value is not BYTE ARRAY!\n", __FUNCTION__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MStorageByteArray *sval = static_cast<MStorageByteArray*>(bval);
|
||||||
|
if(len)
|
||||||
|
*len = sval->getArrayLength();
|
||||||
|
return sval->getByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
double MStorage::getDouble(const std::string &key) {
|
||||||
|
IMStorageBasicType *bval = getBasicType(key);
|
||||||
|
return bval ? bval->getDouble() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MStorage::getByte(const std::string &key) {
|
||||||
|
IMStorageBasicType *bval = getBasicType(key);
|
||||||
|
return bval ? bval->getByte() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MStorage::getString(const std::string &key) {
|
||||||
|
IMStorageBase *bval = getRaw(key);
|
||||||
|
if(!bval){
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if(bval->getType() != MDT_STRING) {
|
||||||
|
fprintf(stderr, "MStorage::%s(): Value is not STRING!\n", __FUNCTION__);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
MStorageString *sval = static_cast<MStorageString*>(bval);
|
||||||
|
return sval->getString();
|
||||||
|
}
|
||||||
|
|
||||||
|
MStorage *MStorage::getGroup(const std::string &key)
|
||||||
|
{
|
||||||
|
IMStorageBase *bval = getRaw(key);
|
||||||
|
if(!bval){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(bval->getType() != MDT_GROUP) {
|
||||||
|
fprintf(stderr, "MStorage::%s(): Value is not GROUP!\n", __FUNCTION__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MStorage *sval = static_cast<MStorage*>(bval);
|
||||||
|
return sval;
|
||||||
|
}
|
||||||
|
|
||||||
|
MValueMapIterator MStorage::begin(){
|
||||||
|
return values.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
MValueMapIterator MStorage::end(){
|
||||||
|
return values.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorage::clear()
|
||||||
|
{
|
||||||
|
MValueMapIterator it = begin();
|
||||||
|
while(it != end()) {
|
||||||
|
delete it->second;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
values.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorage::erase(const std::string &key){
|
||||||
|
IMStorageBase *bval = getRaw(key);
|
||||||
|
if(bval){
|
||||||
|
values.erase(key);
|
||||||
|
delete bval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorage::dbgPrintKeys()
|
||||||
|
{
|
||||||
|
MValueMapIterator it = begin();
|
||||||
|
printf("MStorage: [ ");
|
||||||
|
while(it != end()) {
|
||||||
|
printf("%s ", it->first.c_str());
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
printf("]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
IMStorageBase *MStorage::createByID(uint8_t id) {
|
||||||
|
switch(id) {
|
||||||
|
case MDT_INT32:
|
||||||
|
return new MStorageInt32(0);
|
||||||
|
case MDT_DOUBLE:
|
||||||
|
return new MStorageDouble(0);
|
||||||
|
case MDT_BYTE:
|
||||||
|
return new MStorageByte(0);
|
||||||
|
case MDT_STRING:
|
||||||
|
return new MStorageString("");
|
||||||
|
case MDT_INT32_ARRAY:
|
||||||
|
return new MStorageInt32Array(NULL, 0);
|
||||||
|
case MDT_BYTE_ARRAY:
|
||||||
|
return new MStorageByteArray(NULL, 0);
|
||||||
|
case MDT_GROUP:
|
||||||
|
return new MStorage();
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "MStorage::%s(): "
|
||||||
|
"Unknown data type (0x%02x)!\n", __FUNCTION__, id);
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IMStorageBasicType *MStorage::getBasicType(const std::string &key) {
|
||||||
|
IMStorageBasicType *bval = dynamic_cast<IMStorageBasicType*>(getRaw(key));
|
||||||
|
if(!bval) {
|
||||||
|
fprintf(stderr, "MStorage::%s(): Unable to get Basic type!\n", __FUNCTION__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return bval;
|
||||||
|
}
|
||||||
|
|
||||||
|
MStorageDataType MStorage::getType(){
|
||||||
|
return MDT_GROUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorage::writeData(std::ostream &of){
|
||||||
|
MValueMapIterator it = begin();
|
||||||
|
uint16_t datalen = getLength();
|
||||||
|
of.put((char)getType());
|
||||||
|
of.write((char*)&datalen, sizeof(uint16_t));
|
||||||
|
|
||||||
|
while(it != end()) {
|
||||||
|
size_t klen = it->first.size();
|
||||||
|
of.put((char)(klen & 0xFF));
|
||||||
|
for(size_t pos = 0; pos < klen; ++pos) {
|
||||||
|
of << it->first.at(pos);
|
||||||
|
}
|
||||||
|
it->second->writeData(of);
|
||||||
|
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MStorage::readData(std::istream &ifs){
|
||||||
|
uint16_t blockSize = 0;
|
||||||
|
uint16_t bytesRead = 0;
|
||||||
|
|
||||||
|
ifs.read((char*)&blockSize, sizeof(uint16_t));
|
||||||
|
|
||||||
|
|
||||||
|
while (!ifs.eof() && (bytesRead < blockSize)) {
|
||||||
|
uint8_t klen;
|
||||||
|
ifs.read((char*)&klen, 1); // key length
|
||||||
|
bytesRead += ifs.gcount();
|
||||||
|
|
||||||
|
char* key = new char[klen];
|
||||||
|
ifs.read(key, klen); // key
|
||||||
|
bytesRead += ifs.gcount();
|
||||||
|
|
||||||
|
std::string skey(key, klen);
|
||||||
|
uint8_t dtype;
|
||||||
|
ifs.read((char*)&dtype, 1); // data type
|
||||||
|
bytesRead += ifs.gcount();
|
||||||
|
|
||||||
|
IMStorageBase * data = createByID(dtype);
|
||||||
|
data->readData(ifs); // data
|
||||||
|
bytesRead += data->getLength();
|
||||||
|
|
||||||
|
insertRaw(skey, data);
|
||||||
|
|
||||||
|
delete[] key;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bytesRead != blockSize){
|
||||||
|
fprintf(stderr, "MStorage::%s(): Group block size missmatch "
|
||||||
|
"(0x%04x instead of 0x%04x)!\n", __FUNCTION__, bytesRead, blockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t MStorage::getLength(){
|
||||||
|
uint16_t sz = 0;
|
||||||
|
MValueMapIterator it = begin();
|
||||||
|
//sz+=1; // self data type
|
||||||
|
while(it != end()) {
|
||||||
|
sz+=1; // key len byte
|
||||||
|
sz+=it->first.size(); // key characters
|
||||||
|
sz+=1; // data type byte
|
||||||
|
sz+=it->second->getLength(); // data len
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
218
MStorage.h
Normal file
218
MStorage.h
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
#ifndef MSTORAGE_H
|
||||||
|
#define MSTORAGE_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#define MST_HEADER {'M', 'S', 'T', 0xFA, 0x33}
|
||||||
|
#define MST_HEADER_LEN 5
|
||||||
|
|
||||||
|
static const unsigned char _mst_header[MST_HEADER_LEN] = MST_HEADER;
|
||||||
|
|
||||||
|
enum MStorageDataType {
|
||||||
|
MDT_INT32 = 0x01,
|
||||||
|
MDT_DOUBLE = 0x02,
|
||||||
|
MDT_BYTE = 0x03,
|
||||||
|
MDT_STRING = 0x04,
|
||||||
|
MDT_INT32_ARRAY = 0x05,
|
||||||
|
MDT_BYTE_ARRAY = 0x06,
|
||||||
|
MDT_GROUP = 0xAF
|
||||||
|
};
|
||||||
|
|
||||||
|
class IMStorageBase {
|
||||||
|
public:
|
||||||
|
virtual ~IMStorageBase() {}
|
||||||
|
virtual MStorageDataType getType() = 0;
|
||||||
|
virtual void writeData(std::ostream &of) = 0;
|
||||||
|
virtual void readData(std::istream &ifs) = 0;
|
||||||
|
virtual uint16_t getLength() = 0;
|
||||||
|
//virtual void printValue() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IMStorageBasicType : public IMStorageBase {
|
||||||
|
public:
|
||||||
|
virtual uint8_t getByte() = 0;
|
||||||
|
virtual double getDouble() = 0;
|
||||||
|
virtual int32_t getInt() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MStorageInt32 : public IMStorageBasicType {
|
||||||
|
public:
|
||||||
|
MStorageInt32(int32_t val);
|
||||||
|
MStorageDataType getType();
|
||||||
|
uint8_t getByte();
|
||||||
|
double getDouble();
|
||||||
|
int32_t getInt();
|
||||||
|
void writeData(std::ostream &of);
|
||||||
|
void readData(std::istream &ifs);
|
||||||
|
uint16_t getLength();
|
||||||
|
private:
|
||||||
|
int32_t val;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MStorageDouble : public IMStorageBasicType {
|
||||||
|
public:
|
||||||
|
MStorageDouble(double val);
|
||||||
|
MStorageDataType getType();
|
||||||
|
uint8_t getByte();
|
||||||
|
double getDouble();
|
||||||
|
int32_t getInt();
|
||||||
|
void writeData(std::ostream &of);
|
||||||
|
void readData(std::istream &ifs);
|
||||||
|
uint16_t getLength();
|
||||||
|
private:
|
||||||
|
double val;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MStorageByte : public IMStorageBasicType {
|
||||||
|
public:
|
||||||
|
MStorageByte(int8_t val);
|
||||||
|
MStorageDataType getType();
|
||||||
|
uint8_t getByte();
|
||||||
|
double getDouble();
|
||||||
|
int32_t getInt();
|
||||||
|
void writeData(std::ostream &of);
|
||||||
|
void readData(std::istream &ifs);
|
||||||
|
uint16_t getLength();
|
||||||
|
private:
|
||||||
|
int8_t val;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MStorageString : public IMStorageBase {
|
||||||
|
public:
|
||||||
|
MStorageString(std::string val);
|
||||||
|
MStorageDataType getType();
|
||||||
|
std::string getString();
|
||||||
|
void writeData(std::ostream &of);
|
||||||
|
void readData(std::istream &ifs);
|
||||||
|
uint16_t getLength();
|
||||||
|
private:
|
||||||
|
std::string val;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MStorageInt32Array : public IMStorageBase {
|
||||||
|
public:
|
||||||
|
MStorageInt32Array(int32_t *data, uint16_t len);
|
||||||
|
virtual ~MStorageInt32Array();
|
||||||
|
|
||||||
|
MStorageDataType getType();
|
||||||
|
int32_t * getIntArray();
|
||||||
|
uint16_t getLength();
|
||||||
|
uint16_t getArrayLength();
|
||||||
|
void writeData(std::ostream &of);
|
||||||
|
void readData(std::istream &ifs);
|
||||||
|
private:
|
||||||
|
int32_t *val;
|
||||||
|
uint16_t val_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MStorageByteArray : public IMStorageBase {
|
||||||
|
public:
|
||||||
|
MStorageByteArray(uint8_t *data, uint16_t len){
|
||||||
|
if(!data || len == 0){
|
||||||
|
val_len = 0;
|
||||||
|
val = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
val_len = len;
|
||||||
|
val = new uint8_t[val_len];
|
||||||
|
memcpy(val, data, val_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~MStorageByteArray(){
|
||||||
|
delete [] val;
|
||||||
|
}
|
||||||
|
|
||||||
|
MStorageDataType getType(){
|
||||||
|
return MDT_BYTE_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t * getByteArray(){
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getLength(){
|
||||||
|
return val_len + sizeof(uint16_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getArrayLength(){
|
||||||
|
return val_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeData(std::ostream &of){
|
||||||
|
of.put((char)getType());
|
||||||
|
of.write((char*)&val_len, sizeof(uint16_t));
|
||||||
|
of.write((char*)val, val_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void readData(std::istream &ifs){
|
||||||
|
if(val)
|
||||||
|
delete[] val;
|
||||||
|
ifs.read((char*)&val_len, sizeof(uint16_t));
|
||||||
|
val = new uint8_t[val_len];
|
||||||
|
ifs.read((char*)val, val_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t *val;
|
||||||
|
uint16_t val_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::map<const std::string, IMStorageBase*> MValueMap;
|
||||||
|
typedef MValueMap::iterator MValueMapIterator;
|
||||||
|
|
||||||
|
class MStorage : public IMStorageBase {
|
||||||
|
public:
|
||||||
|
MStorage();
|
||||||
|
virtual ~MStorage();
|
||||||
|
|
||||||
|
int8_t writeToFile(std::string fname);
|
||||||
|
int8_t readFromFile(std::string fname);
|
||||||
|
|
||||||
|
void insertRaw(const std::string &key, IMStorageBase *val);
|
||||||
|
IMStorageBase* getRaw(const std::string &key);
|
||||||
|
|
||||||
|
void setInt(const std::string &key, uint32_t val);
|
||||||
|
void setIntArray(const std::string &key, int32_t *val, uint16_t len);
|
||||||
|
void setByteArray(const std::string &key, uint8_t *val, uint16_t len);
|
||||||
|
void setDouble(const std::string &key, double val);
|
||||||
|
void setByte(const std::string &key, uint8_t val);
|
||||||
|
void setString(const std::string &key, std::string val);
|
||||||
|
void setGroup(const std::string &key, MStorage *group);
|
||||||
|
|
||||||
|
int32_t getInt(const std::string &key);
|
||||||
|
int32_t* getIntArray(const std::string &key, uint16_t *len);
|
||||||
|
uint8_t* getByteArray(const std::string &key, uint16_t *len);
|
||||||
|
double getDouble(const std::string &key);
|
||||||
|
uint8_t getByte(const std::string &key);
|
||||||
|
std::string getString(const std::string &key);
|
||||||
|
MStorage* getGroup(const std::string &key);
|
||||||
|
|
||||||
|
|
||||||
|
MValueMapIterator begin();
|
||||||
|
MValueMapIterator end();
|
||||||
|
void clear();
|
||||||
|
void erase(const std::string &key);
|
||||||
|
void dbgPrintKeys();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static IMStorageBase* createByID(uint8_t id);
|
||||||
|
IMStorageBasicType* getBasicType(const std::string &key);
|
||||||
|
MValueMap values;
|
||||||
|
|
||||||
|
// IMStorageBase
|
||||||
|
public:
|
||||||
|
MStorageDataType getType();
|
||||||
|
void writeData(std::ostream &of);
|
||||||
|
void readData(std::istream &ifs);
|
||||||
|
uint16_t getLength();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MSTORAGE_H
|
62
README.md
Normal file
62
README.md
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
MStorage - simple multi-type map storage for some fixed data types
|
||||||
|
==================================================================
|
||||||
|
|
||||||
|
Absolutely no warranty. Use at your own risk.
|
||||||
|
Written for one small game.
|
||||||
|
|
||||||
|
### Supported types:
|
||||||
|
- 32-bit Signed Integer
|
||||||
|
- 32-bit Signed Integer Array
|
||||||
|
- 8-bit Unsigned Integer (Byte)
|
||||||
|
- 8-bit Unsigned Integer (Byte) Array
|
||||||
|
- Double
|
||||||
|
- String (std::string)
|
||||||
|
|
||||||
|
### Features:
|
||||||
|
- Values and groups are associated with keys.
|
||||||
|
- Grouping. All of types listed above can be grouped.
|
||||||
|
- Base types are casted automatically to each other.
|
||||||
|
- Writing to file / reading from file.
|
||||||
|
- Writing and reading from stream.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Example usage:
|
||||||
|
|
||||||
|
### Assigning and writing to file:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
MStorage mst;
|
||||||
|
mst.setInt("someInt", 123456);
|
||||||
|
mst.writeToFile("data.mst");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reading:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
MStorage mst;
|
||||||
|
mst.readFromFile("data.mst");
|
||||||
|
int32_t val = mst.getInt("someInt");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Groups:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
MStorage mst;
|
||||||
|
MStorage *group = new MStorage();
|
||||||
|
group->setString("str", "Hello");
|
||||||
|
mst.setGroup("someGroup", group);
|
||||||
|
|
||||||
|
std::string str = mst.getGroup("someGroup")->getString("str");
|
||||||
|
```
|
||||||
|
### Iterating:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
MValueMapIterator it = mst.begin();
|
||||||
|
while(it != mst.end()) {
|
||||||
|
MStorageBase *val = it->second;
|
||||||
|
// do something
|
||||||
|
// type can be discovered via val->getType()
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
```
|
6
example/Makefile.linux
Normal file
6
example/Makefile.linux
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
RM = rm -f
|
||||||
|
TO_NULL = > /dev/null
|
||||||
|
TARGET_BINARY = example
|
||||||
|
OS_SEPARATOR= /
|
||||||
|
|
||||||
|
-include base.mk
|
6
example/Makefile.win32
Normal file
6
example/Makefile.win32
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
RM = del /f
|
||||||
|
TO_NULL = 2>NUL
|
||||||
|
TARGET_BINARY = example.exe
|
||||||
|
OS_SEPARATOR= \\
|
||||||
|
|
||||||
|
-include base.mk
|
48
example/base.mk
Normal file
48
example/base.mk
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
SOURCES = example.cpp ./../MStorage.cpp
|
||||||
|
|
||||||
|
LDFLAGS_RELEASE = -s
|
||||||
|
CDFLAGS_RELEASE = -O2 -Wall
|
||||||
|
|
||||||
|
CFLAGS ?= -g -Wall
|
||||||
|
LDPATH ?= -L.
|
||||||
|
LDFLAGS ?=
|
||||||
|
INCLUDES = -I. -I./..
|
||||||
|
|
||||||
|
OBJECTS = $(SOURCES:.cpp=.o)
|
||||||
|
OBJECTS := $(OBJECTS:.c=.o)
|
||||||
|
DEPS = $(OBJECTS:.o=.d)
|
||||||
|
|
||||||
|
TARGET = $(TARGET_BINARY)
|
||||||
|
|
||||||
|
|
||||||
|
all: debug
|
||||||
|
|
||||||
|
release: LDFLAGS=$(LDFLAGS_RELEASE)
|
||||||
|
release: CFLAGS=$(CDFLAGS_RELEASE)
|
||||||
|
release: debug
|
||||||
|
|
||||||
|
|
||||||
|
debug: $(SOURCES) $(TARGET)
|
||||||
|
|
||||||
|
|
||||||
|
$(TARGET): $(OBJECTS)
|
||||||
|
$(CXX) $(LDPATH) -o $@ $(OBJECTS) $(LDFLAGS)
|
||||||
|
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CXX) -c -MMD -MP $(CFLAGS) $(INCLUDES) $< -o $@
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) -c -MMD -MP $(CFLAGS) $(INCLUDES) $< -o $@
|
||||||
|
|
||||||
|
.PHONY: clean debug release
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) *.o $(TO_NULL)
|
||||||
|
$(RM) *.d $(TO_NULL)
|
||||||
|
$(RM) .$(OS_SEPARATOR)..$(OS_SEPARATOR)*.o $(TO_NULL)
|
||||||
|
$(RM) .$(OS_SEPARATOR)..$(OS_SEPARATOR)*.d $(TO_NULL)
|
||||||
|
$(RM) $(TARGET_BINARY) $(TO_NULL)
|
||||||
|
$(RM) data.mst $(TO_NULL)
|
||||||
|
|
||||||
|
-include $(DEPS)
|
57
example/example.cpp
Normal file
57
example/example.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include "MStorage.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void print_fieds(MStorage *mst) {
|
||||||
|
printf("someString: %s\n", mst->getString("someString").c_str());
|
||||||
|
printf("someInt: %d\n", mst->getInt("someInt"));
|
||||||
|
printf("someByte: 0x%x\n", mst->getByte("someByte"));
|
||||||
|
|
||||||
|
printf("someGroup: \n");
|
||||||
|
MStorage* group = mst->getGroup("someGroup");
|
||||||
|
printf(" someDouble: %.9f\n", group->getDouble("someDouble"));
|
||||||
|
//or mst->getGroup("someGroup")->getDouble("someDouble")
|
||||||
|
|
||||||
|
int32_t* arr;
|
||||||
|
uint16_t arr_len;
|
||||||
|
arr = group->getIntArray("someIntArray", &arr_len);
|
||||||
|
if (arr) {
|
||||||
|
printf(" someIntArray: ");
|
||||||
|
for (int i = 0; i < arr_len; ++i) {
|
||||||
|
printf("%d ", arr[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[]) {
|
||||||
|
MStorage *storage;
|
||||||
|
|
||||||
|
printf("\n## write test ##\n");
|
||||||
|
storage = new MStorage();
|
||||||
|
|
||||||
|
storage->setString("someString", "Hello world!");
|
||||||
|
storage->setInt("someInt", 123456);
|
||||||
|
storage->setByte("someByte", 0xA4);
|
||||||
|
|
||||||
|
MStorage *group = new MStorage(); // you can create groups in groups too
|
||||||
|
group->setDouble("someDouble", 3.141592653);
|
||||||
|
int32_t _ints[] = {42, 34, 32323, 5573453};
|
||||||
|
group->setIntArray("someIntArray", _ints, 4); // array is being copied
|
||||||
|
|
||||||
|
storage->setGroup("someGroup", group);
|
||||||
|
|
||||||
|
print_fieds(storage);
|
||||||
|
storage->writeToFile("data.mst");
|
||||||
|
delete storage; // subfields are deleted automatically
|
||||||
|
|
||||||
|
|
||||||
|
printf("\n## read test ##\n");
|
||||||
|
storage = new MStorage();
|
||||||
|
storage->readFromFile("data.mst");
|
||||||
|
print_fieds(storage);
|
||||||
|
delete storage;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user