使用rapidjson实现了TouchVG的序列化适配器类

外部接口类隐藏JSON细节:

#ifndef __GEOMETRY_JSONSTORAGE_H_
#define __GEOMETRY_JSONSTORAGE_H_

struct MgStorage;

//! JSON序列化适配器类
/*! \ingroup GEOM_SHAPE
*/
class MgJsonStorage
{
public:
    MgJsonStorage();
    ~MgJsonStorage();

    //! 给定JSON内容,返回存取接口对象以便开始读取
    MgStorage* storageForRead(const char* content);

    //! 返回存取接口对象以便开始写数据,写完可调用 getContentWriten()
    MgStorage* storageForWrite();

    //! 返回写完后的JSON内容
    const char* getContentWriten() const;

private:
    class Impl;
    Impl* _impl;
};

#endif // __GEOMETRY_JSONSTORAGE_H_

 

内部实现文件使用rapidjson框架,代码少、运行速度比iOS和Android的Json框架快。

#include "mgjsonstorage.h"
#include <mgstorage.h>
#include <vector>
#include "rapidjson/document.h"     // rapidjson's DOM-style API
#include "rapidjson/prettywriter.h" // for stringify JSON
#include "rapidjson/filestream.h"   // wrapper of C stream for prettywriter as output
#include "rapidjson/stringbuffer.h"

using namespace rapidjson;

//! JSON序列化适配器类,内部实现类
class MgJsonStorage::Impl : public MgStorage
{
public:
    Impl() {}

    void clear();
    const char* getContent() const;
    void setContent(const char* content);

private:
    bool readNode(const char* name, int index, bool ended);
    bool writeNode(const char* name, int index, bool ended);

    int readInt(const char* name, int defvalue);
    bool readBool(const char* name, bool defvalue);
    float readFloat(const char* name, float defvalue);
    int readFloatArray(const char* name, float* values, int count);
    int readString(const char* name, char* value, int count);

    void writeInt(const char* name, int value);
    void writeBool(const char* name, bool value);
    void writeFloat(const char* name, float value);
    void writeFloatArray(const char* name, const float* values, int count);
    void writeString(const char* name, const char* value);

private:
    Document _doc;
    std::vector<Value*> _stack;
    StringBuffer _strbuf;
};

MgJsonStorage::MgJsonStorage()
{
    _impl = new Impl();
}

MgJsonStorage::~MgJsonStorage()
{
    delete _impl;
}

const char* MgJsonStorage::getContentWriten() const
{
    return _impl->getContent();
}

MgStorage* MgJsonStorage::storageForRead(const char* content)
{
    _impl->clear();
    _impl->setContent(content);

    return _impl;
}

MgStorage* MgJsonStorage::storageForWrite()
{
    _impl->clear();

    return _impl;
}

void MgJsonStorage::Impl::clear()
{
    _doc.SetNull();
    _stack.clear();
    _strbuf.Clear();
}

const char* MgJsonStorage::Impl::getContent() const
{
    return _strbuf.GetString();
}

void MgJsonStorage::Impl::setContent(const char* content)
{
    if (content && *content) {
        _doc.Parse<0>(content);         // DOM解析
        if (_doc.HasParseError()) {
            const char* err = _doc.GetParseError();
            err = err;
        }
    }
}

bool MgJsonStorage::Impl::readNode(const char* name, int index, bool ended)
{
    if (!ended) {                       // 开始一个新节点
        char tmpname[32];
        if (index >= 0) {               // 形成实际节点名称
            sprintf(tmpname, "%s%d", name, index + 1);
            name = tmpname;
        }

        Value &parent = _stack.empty() ? _doc : *_stack.back();

        if (!parent.IsObject() || !parent.HasMember(name)) {    // 没有节点则返回
            return false;
        }

        _stack.push_back(&parent[name]);    // 当前JSON对象压栈
    }
    else {                              // 当前节点读取完成
        if (!_stack.empty()) {
            _stack.pop_back();          // 出栈
        }
        if (_stack.empty()) {           // 根节点已出栈
            clear();
        }
    }

    return true;
}

int MgJsonStorage::Impl::readInt(const char* name, int defvalue)
{
    int ret = defvalue;
    Value *node = _stack.empty() ? NULL : _stack.back();

    if (node && node->HasMember(name)) {
        const Value &item = (*node)[name];

        if (item.IsInt()) {
            ret = item.GetInt();
        }
        else if (item.IsUint()) {
            ret = item.GetUint();
        }
        else {
            ret = ret;
        }
    }

    return ret;
}

bool MgJsonStorage::Impl::readBool(const char* name, bool defvalue)
{
    bool ret = defvalue;
    Value *node = _stack.empty() ? NULL : _stack.back();

    if (node && node->HasMember(name)) {
        const Value &item = node->GetMember(name);

        if (item.IsBool()) {
            ret = item.GetBool();
        }
        else {
            ret = ret;
        }
    }

    return ret;
}

float MgJsonStorage::Impl::readFloat(const char* name, float defvalue)
{
    float ret = defvalue;
    Value *node = _stack.empty() ? NULL : _stack.back();

    if (node && node->HasMember(name)) {
        const Value &item = node->GetMember(name);

        if (item.IsDouble()) {
            ret = (float)item.GetDouble();
        }
        else if (item.IsInt()) {    // 浮点数串可能没有小数点,需要判断整数
            ret = (float)item.GetInt();
        }
        else {
            ret = ret;
        }
    }

    return ret;
}

int MgJsonStorage::Impl::readFloatArray(const char* name, float* values, int count)
{
    int ret = 0;
    Value *node = _stack.empty() ? NULL : _stack.back();

    if (node && node->HasMember(name)) {
        const Value &item = node->GetMember(name);

        if (item.IsArray()) {
            ret = item.Size();
            if (values) {
                count = ret < count ? ret : count;
                ret = 0;
                for (int i = 0; i < count; i++) {
                    const Value &v = item[i];

                    if (v.IsDouble()) {
                        values[ret++] = (float)v.GetDouble();
                    }
                    else if (v.IsInt()) {
                        values[ret++] = (float)v.GetInt();
                    }
                    else {
                        ret = ret;
                    }
                }
            }
        }
        else {
            ret = ret;
        }
    }

    return ret;
}

int MgJsonStorage::Impl::readString(const char* name, char* value, int count)
{
    int ret = 0;
    Value *node = _stack.empty() ? NULL : _stack.back();

    if (node && node->HasMember(name)) {
        const Value &item = node->GetMember(name);

        if (item.IsString()) {
            ret = item.GetStringLength();
            if (value) {
                ret = ret < count ? ret : count;
                strncpy(value, item.GetString(), ret);
            }
        }
        else {
            ret = ret;
        }
    }

    return ret;
}

bool MgJsonStorage::Impl::writeNode(const char* name, int index, bool ended)
{
    if (!ended) {                       // 开始一个新节点
        char tmpname[32];
        if (index >= 0) {               // 形成实际节点名称
            sprintf(tmpname, "%s%d", name, index + 1);
            name = tmpname;
        }

        if (_stack.empty()) {
            _doc.SetObject();
        }

        Value &parent = _stack.empty() ? _doc : *_stack.back();
        Value tmpnode(kObjectType);
        Value namenode(name, _doc.GetAllocator());  // 节点名是临时串,要复制
        
        parent.AddMember(namenode, tmpnode, _doc.GetAllocator());
        _stack.push_back(&(parent.MemberEnd() - 1)->value); // 新节点压栈
    }
    else {                              // 当前节点写完
        if (!_stack.empty()) {
            _stack.pop_back();          // 出栈
        }
        if (_stack.empty()) {           // 根节点已出栈
            Document::AllocatorType allocator;
            Writer<StringBuffer> writer(_strbuf, &allocator);
            _doc.Accept(writer);        // DOM树转换到文本流

            _doc.SetNull();
            _stack.clear();
        }
    }

    return true;
}

void MgJsonStorage::Impl::writeInt(const char* name, int value)
{
    _stack.back()->AddMember(name, value, _doc.GetAllocator());
}

void MgJsonStorage::Impl::writeBool(const char* name, bool value)
{
    _stack.back()->AddMember(name, value, _doc.GetAllocator());
}

void MgJsonStorage::Impl::writeFloat(const char* name, float value)
{
    _stack.back()->AddMember(name, (double)value, _doc.GetAllocator());
}

void MgJsonStorage::Impl::writeFloatArray(const char* name, const float* values, int count)
{
    Value node(kArrayType);

    for (int i = 0; i < count; i++) {
        node.PushBack((double)values[i], _doc.GetAllocator());
    }
    _stack.back()->AddMember(name, node, _doc.GetAllocator());
}

void MgJsonStorage::Impl::writeString(const char* name, const char* value)
{
    _stack.back()->AddMember(name, value, _doc.GetAllocator());
}

 

 

posted @ 2013-01-07 23:16  张云贵  Views(2420)  Comments(0Edit  收藏  举报