浅析avro序列化和反序列化源码及提供两种数据序列存储思路

以hadoop的avro实现原理做引子:

varo的测试样例程序

#include <complex>

#include "avro/Encoder.hh"
#include "avro/Decoder.hh"
#include "avro/Specific.hh"

namespace avro {
template<typename T>
struct codec_traits<std::complex<T> > {
    static void encode(Encoder& e, const std::complex<T>& c) {
        avro::encode(e, std::real(c));
        avro::encode(e, std::imag(c));
    }

    static void decode(Decoder& d, std::complex<T>& c) {
        T re, im;
        avro::decode(d, re);
        avro::decode(d, im);
        c = std::complex<T>(re, im);
    }
};

}
int
main()
{
    std::auto_ptr<avro::OutputStream> out = avro::memoryOutputStream();
    avro::EncoderPtr e = avro::binaryEncoder();
    e->init(*out);
    std::complex<double> c1(1.0, 2.0);
    avro::encode(*e, c1);

    std::auto_ptr<avro::InputStream> in = avro::memoryInputStream(*out);
    avro::DecoderPtr d = avro::binaryDecoder();
    d->init(*in);

    std::complex<double> c2;
    avro::decode(*d, c2);
    std::cout << '(' << std::real(c2) << ", " << std::imag(c2) << ')' << std::endl;
    return 0;
}

这个样例相对简单。

其中template <typename T>

    struct codec_traits {  };  

为avro对不同数据类型存储实现的模板类特化。

由于avro的基础库类未有提供std::complex<double>的特化说明,故在样例函数添加avro作用域的complex类型说明,并将复数类型的特化函数转化为avro提供的基础数据类型的特化

特化函数定义在avro  api/specific.hh 头文件中定义。样例这里使用了 143行定义的double类型处理

template <> struct codec_traits<double> {
    /**
     * Encodes a given value.
     */
    static void encode(Encoder& e, double d) {
        e.encodeDouble(d);
    }
    /**
     * Decodes into a given value.
     */
    static void decode(Decoder& d, double& dbl) {
        dbl = d.decodeDouble();
    }

};

这里说明下avro内部存储数据的结构:

由于样例中使用的是 二进制编制的内存存储形式(相对于文件存储)

std::auto_ptr<avro::OutputStream> out = avro::memoryOutputStream();

avro::EncoderPtr e = avro::binaryEncoder();

其中 :memoryOutputStream 数据保存内存存储类

           binaryEncoder  存储数据写入管理类  --- 对应Impl/binaryEncoder.cc文件

double写入内存函数实现:

void BinaryEncoder::encodeDouble(double d)
{
    const uint8_t* p = reinterpret_cast<const uint8_t*>(&d);
    out_.writeBytes(p, sizeof(double));
}

out为MemoryOutputStream管理类。对应文件实现impl/stream.cc 文件

其存储形式如下图。如上例中c1(1.0,2.0)。其中图示每一个方格为一个double存储单元。


写入逻辑实现为:

1.检测当前空间,如上图中一行是否足够double写入(注每次申请行为固定个数double存储单元)。否申请新的空间(即如上  图一行)

2.写入double数据,并记录当前写入地址及最大可写入地址。

以上为数据写入的实现,反之取出,只需要按顺序读取数值出来即可。

难点:avro特化函数对指定数据类型的处理


另外提供两种序列化和反序列化实现:

第一种:来自哥们写的。特复杂也很难理解,(我也看了好几天才懂~~),仅给出部分关键文件源码。

想看完整源码 可在github下载 :https://github.com/xyz347/x2struct

以json序列化为例源码示例:

X2Struct.hh  这个文件是关键,以宏遍历的形式对结构体成员进行逐个成员展开处理。如果想实现非json存储数据类型的数据序列化和反序列化也以这个文件为基础构建。

特别注意:结构体成员展开为二层次展开,(怎么理解,看代码~~~~)。结构体成员最大展开个数为 32*32


#ifndef __X_TO_STRUCT_HPP
#define __X_TO_STRUCT_HPP

#include <string>
#include <set>
#include <stdexcept>
#include "xobj.hpp"

#include "xmlstr.hpp"
#include "jsoncfgstr.hpp"

#ifdef XTOSTRUCT_GEN_GOLANG_CODE
#include <typeinfo>
#include "gostr.hpp"
#endif
//#include <iostream>
//using namespace std;

namespace x2struct {

#define X2STRUCT_OPT_ME     "me"    // must exist

class X {
public:
    template <typename TYPE>
    static bool loadjson(const std::string&str, TYPE&t, bool isfile=true) {
        JsonObj obj(str, isfile);
        t.__x_to_struct(obj);
        return true;
    }   

    template <typename TYPE>
    static std::string tojson(const TYPE&t, const std::string&root, bool newline=true, int space=4) {
        JsonCfgStr obj(true, newline, space);
        t.__struct_to_str(obj, root, 0);
        return obj.toStr();
    }

};

#define X_STRUCT_FUNC_TOX_BEGIN                                             \
private:                                                                    \
    std::set<std::string> __x_has_string;                                   \
public:                                                                     \
    bool xhas(const std::string& name) const {                              \
        return __x_has_string.find(name)!=__x_has_string.end();             \
    }                                                                       \
    bool __x_condition(x2struct::XObj& obj, const std::string&name) {       \
        (void)obj;(void)name;                                               \
        return true;                                                        \
    }                                                                       \
    void __x_to_struct(x2struct::XObj& obj) {

#define X_STRUCT_ACT_TOX_O(M)                                               \
        if (obj.has(#M)) {                                                  \
            obj[#M].convert(M);                                             \
            __x_has_string.insert(#M);                                      \
        }

#define X_STRUCT_ACT_TOX_M(M)                                               \
        if (obj.has(#M)) {                                                  \
            obj[#M].convert(M);                                             \
            __x_has_string.insert(#M);                                      \
        } else {                                                            \
            obj.me_exception(#M);                                           \
        }

// aliase name
#define X_STRUCT_ACT_TOX_A(M, A_NAME)                                       \
    {                                                                       \
        bool me = false;                                                    \
        std::string __alias__name__ = obj.hasa(#M, A_NAME, me);             \
        if (!__alias__name__.empty()) {                                     \
            obj[__alias__name__].convert(M);                                \
            __x_has_string.insert(#M);                                      \
        } else if (me) {                                                    \
            obj.me_exception(#M);                                           \
        }                                                                   \
    }

#define X_STRUCT_FUNC_TOX_END }


// struct to string
#define X_STRUCT_FUNC_TOS_BEGIN                                                     \
    template <class CLASS>                                                          \
    void __struct_to_str(CLASS& obj, const std::string&root, int splen) const {     \
        int index = 0;                                                              \
        obj.begin(root, splen);

#define X_STRUCT_ACT_TOS_O(M)                                                       \
        obj.convert(#M, M, splen+obj.space(), index++);

#define X_STRUCT_ACT_TOS_A(M, A_NAME)                                               \
        obj.convert(obj.fieldName(#M,A_NAME), M, splen+obj.space(), index++);

#define X_STRUCT_FUNC_TOS_END                                                       \
        obj.end(root,splen);                                                        \
    }

    
// struct to golang code
#define X_STRUCT_FUNC_TOG_BEGIN                                                     \
    std::string __struct_to_go(x2struct::GoCode &obj) const {                       \
        obj.set_type_id_name(typeid(*this).name());

#define X_STRUCT_ACT_TOG_O(M)                                                       \
        obj.convert(M, #M);

#define X_STRUCT_ACT_TOG_A(M, A_NAME)                                               \
        obj.convert(M, #M, A_NAME);

#define X_STRUCT_FUNC_TOG_END                                                       \
        return obj.str();                                                           \
    }


// lenght should equal X_STRUCT_N
#define X_DEC_LIST _32,_31,_30,_29,_28,_27,_26,_25,_24,_23,_22,_21,_20,_19,_18,_17,_16,_15,_14,_13,_12,_11,_10,_9,_8,_7,_6,_5,_4,_3,_2,_1
// expand macro depend on parameters number
#define X_STRUCT_N(ACTION,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,N,...) ACTION##N

/*
    work with X_STRUCT_N to expand macro
    struct MyX {
        int         a;
        std::string b;
        double      c;
        XTOSTRUCT(A(a,"_id"), O(b,c));
    };
    there'r two layer in this macro:
    l1: A(a,"_id"), O(b,c)
    l2: a,"_id"; b,c
    so we need expand twice
*/

// wrap X_STRUCT_N. so we can use X_DEC_LIST
#define X_STRUCT_WRAP_L1(ACT, LIST, ...) X_STRUCT_N(X_STRUCT_L1, __VA_ARGS__, LIST)(ACT, __VA_ARGS__)
#define X_STRUCT_WRAP_L2(ACT, LIST, ...) X_STRUCT_N(X_STRUCT_L2, __VA_ARGS__, LIST)(ACT, __VA_ARGS__)

#define X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_##ACT##M
#define X_STRUCT_L1_1(ACT, M)        X_STRUCT_L1_DEF(ACT, M)
#define X_STRUCT_L1_2(ACT, M,...)    X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_1(ACT, __VA_ARGS__)
#define X_STRUCT_L1_3(ACT, M,...)    X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_2(ACT, __VA_ARGS__)
#define X_STRUCT_L1_4(ACT, M,...)    X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_3(ACT, __VA_ARGS__)
#define X_STRUCT_L1_5(ACT, M,...)    X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_4(ACT, __VA_ARGS__)
#define X_STRUCT_L1_6(ACT, M,...)    X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_5(ACT, __VA_ARGS__)
#define X_STRUCT_L1_7(ACT, M,...)    X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_6(ACT, __VA_ARGS__)
#define X_STRUCT_L1_8(ACT, M,...)    X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_7(ACT, __VA_ARGS__)
#define X_STRUCT_L1_9(ACT, M,...)    X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_8(ACT, __VA_ARGS__)
#define X_STRUCT_L1_10(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_9(ACT, __VA_ARGS__)
#define X_STRUCT_L1_11(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_10(ACT, __VA_ARGS__)
#define X_STRUCT_L1_12(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_11(ACT, __VA_ARGS__)
#define X_STRUCT_L1_13(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_12(ACT, __VA_ARGS__)
#define X_STRUCT_L1_14(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_13(ACT, __VA_ARGS__)
#define X_STRUCT_L1_15(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_14(ACT, __VA_ARGS__)
#define X_STRUCT_L1_16(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_15(ACT, __VA_ARGS__)
#define X_STRUCT_L1_17(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_16(ACT, __VA_ARGS__)
#define X_STRUCT_L1_18(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_17(ACT, __VA_ARGS__)
#define X_STRUCT_L1_19(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_18(ACT, __VA_ARGS__)
#define X_STRUCT_L1_20(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_19(ACT, __VA_ARGS__)
#define X_STRUCT_L1_21(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_20(ACT, __VA_ARGS__)
#define X_STRUCT_L1_22(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_21(ACT, __VA_ARGS__)
#define X_STRUCT_L1_23(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_22(ACT, __VA_ARGS__)
#define X_STRUCT_L1_24(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_23(ACT, __VA_ARGS__)
#define X_STRUCT_L1_25(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_24(ACT, __VA_ARGS__)
#define X_STRUCT_L1_26(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_25(ACT, __VA_ARGS__)
#define X_STRUCT_L1_27(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_26(ACT, __VA_ARGS__)
#define X_STRUCT_L1_28(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_27(ACT, __VA_ARGS__)
#define X_STRUCT_L1_29(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_28(ACT, __VA_ARGS__)
#define X_STRUCT_L1_30(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_29(ACT, __VA_ARGS__)
#define X_STRUCT_L1_31(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_30(ACT, __VA_ARGS__)
#define X_STRUCT_L1_32(ACT, M,...)   X_STRUCT_L1_DEF(ACT, M)      X_STRUCT_L1_31(ACT, __VA_ARGS__)

#define X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_ACT_##ACT(M)
#define X_STRUCT_L2_1(ACT, M)       X_STRUCT_L2_DEF(ACT, M)
#define X_STRUCT_L2_2(ACT, M,...)   X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_1(ACT, __VA_ARGS__)
#define X_STRUCT_L2_3(ACT, M,...)   X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_2(ACT, __VA_ARGS__)
#define X_STRUCT_L2_4(ACT, M,...)   X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_3(ACT, __VA_ARGS__)
#define X_STRUCT_L2_5(ACT, M,...)   X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_4(ACT, __VA_ARGS__)
#define X_STRUCT_L2_6(ACT, M,...)   X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_5(ACT, __VA_ARGS__)
#define X_STRUCT_L2_7(ACT, M,...)   X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_6(ACT, __VA_ARGS__)
#define X_STRUCT_L2_8(ACT, M,...)   X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_7(ACT, __VA_ARGS__)
#define X_STRUCT_L2_9(ACT, M,...)   X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_8(ACT, __VA_ARGS__)
#define X_STRUCT_L2_10(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_9(ACT, __VA_ARGS__)
#define X_STRUCT_L2_11(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_10(ACT, __VA_ARGS__)
#define X_STRUCT_L2_12(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_11(ACT, __VA_ARGS__)
#define X_STRUCT_L2_13(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_12(ACT, __VA_ARGS__)
#define X_STRUCT_L2_14(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_13(ACT, __VA_ARGS__)
#define X_STRUCT_L2_15(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_14(ACT, __VA_ARGS__)
#define X_STRUCT_L2_16(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_15(ACT, __VA_ARGS__)
#define X_STRUCT_L2_17(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_16(ACT, __VA_ARGS__)
#define X_STRUCT_L2_18(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_17(ACT, __VA_ARGS__)
#define X_STRUCT_L2_19(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_18(ACT, __VA_ARGS__)
#define X_STRUCT_L2_20(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_19(ACT, __VA_ARGS__)
#define X_STRUCT_L2_21(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_20(ACT, __VA_ARGS__)
#define X_STRUCT_L2_22(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_21(ACT, __VA_ARGS__)
#define X_STRUCT_L2_23(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_22(ACT, __VA_ARGS__)
#define X_STRUCT_L2_24(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_23(ACT, __VA_ARGS__)
#define X_STRUCT_L2_25(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_24(ACT, __VA_ARGS__)
#define X_STRUCT_L2_26(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_25(ACT, __VA_ARGS__)
#define X_STRUCT_L2_27(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_26(ACT, __VA_ARGS__)
#define X_STRUCT_L2_28(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_27(ACT, __VA_ARGS__)
#define X_STRUCT_L2_29(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_28(ACT, __VA_ARGS__)
#define X_STRUCT_L2_30(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_29(ACT, __VA_ARGS__)
#define X_STRUCT_L2_31(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_30(ACT, __VA_ARGS__)
#define X_STRUCT_L2_32(ACT, M,...)  X_STRUCT_L2_DEF(ACT, M)     X_STRUCT_L2_31(ACT, __VA_ARGS__)

// L1 action define. O M A
// string to struct
#define X_STRUCT_L1_TOX_O(...)  X_STRUCT_WRAP_L2(TOX_O, X_DEC_LIST, __VA_ARGS__)
#define X_STRUCT_L1_TOX_M(...)  X_STRUCT_WRAP_L2(TOX_M, X_DEC_LIST, __VA_ARGS__)
#define X_STRUCT_L1_TOX_A(M,A)  X_STRUCT_ACT_TOX_A(M,A)

// struct to string
#define X_STRUCT_L1_TOS_O(...)  X_STRUCT_WRAP_L2(TOS_O, X_DEC_LIST, __VA_ARGS__)
#define X_STRUCT_L1_TOS_M       X_STRUCT_L1_TOS_O
#define X_STRUCT_L1_TOS_A(M,A)  X_STRUCT_ACT_TOS_A(M,A)

// struct to golang code
#define X_STRUCT_L1_TOG_O(...)  X_STRUCT_WRAP_L2(TOG_O, X_DEC_LIST, __VA_ARGS__)
#define X_STRUCT_L1_TOG_M       X_STRUCT_L1_TOG_O
#define X_STRUCT_L1_TOG_A(M,A)  X_STRUCT_ACT_TOG_A(M,A)


#ifdef XTOSTRUCT_GEN_GOLANG_CODE
#define XTOSTRUCT(...)  \
    X_STRUCT_FUNC_TOX_BEGIN  X_STRUCT_WRAP_L1(TOX_, X_DEC_LIST, __VA_ARGS__) X_STRUCT_FUNC_TOX_END  \
    X_STRUCT_FUNC_TOS_BEGIN  X_STRUCT_WRAP_L1(TOS_, X_DEC_LIST, __VA_ARGS__) X_STRUCT_FUNC_TOS_END  \
    X_STRUCT_FUNC_TOG_BEGIN  X_STRUCT_WRAP_L1(TOG_, X_DEC_LIST, __VA_ARGS__) X_STRUCT_FUNC_TOG_END
#else
#define XTOSTRUCT(...)  \
    X_STRUCT_FUNC_TOX_BEGIN  X_STRUCT_WRAP_L1(TOX_, X_DEC_LIST, __VA_ARGS__) X_STRUCT_FUNC_TOX_END  \
    X_STRUCT_FUNC_TOS_BEGIN  X_STRUCT_WRAP_L1(TOS_, X_DEC_LIST, __VA_ARGS__) X_STRUCT_FUNC_TOS_END
#endif


#define XTOSTRUCT_CONDITION()   bool __x_condition(x2struct::XObj& obj, const char* name)
#define XTOSTRUCT_CONDITION_EQ(attr1, attr2)                    \
    bool __x_condition(x2struct::XObj& obj, const char* name) { \
        return obj.attribute(attr1)==obj.attribute(attr2);      \
    }

}

#endif

jsonstrcfg.h  json序列化和反序列化接口定义


* Copyright (C) 2017 YY Inc. All rights reserved.
*
* Licensed 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.
*/


#ifndef __X_TO_STRUCT_JSON_CFG_STR_HPP
#define __X_TO_STRUCT_JSON_CFG_STR_HPP

#include <stdint.h>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <sstream>
#include <boost/lexical_cast.hpp>

#include "xstr.hpp"

namespace x2struct {

class JsonCfgStr:public XStr {
public:
    JsonCfgStr(bool isjson, bool newline=false, int splen=4);
    ~JsonCfgStr();
public:
    void begin(const std::string&root, int splen);
    void end(const std::string&root, int splen);
    int  space();
    std::string toStr() const;
public:
    virtual void convert(const std::string&name, const std::string& data, int space, int index);

    // base type
    void convert(const std::string&name, int16_t data, int splen, int index);
    void convert(const std::string&name, uint16_t data, int splen, int index);
    void convert(const std::string&name, int32_t data, int splen, int index);
    void convert(const std::string&name, uint32_t data, int splen, int index);
    void convert(const std::string&name, int64_t data, int splen, int index);
    void convert(const std::string&name, uint64_t data, int splen, int index);
    void convert(const std::string&name, float data, int splen, int index);
    void convert(const std::string&name, double data, int splen, int index);
    void convert(const std::string&name, bool data, int splen, int index);

    // base type vector
    void convert(const std::string&name, const std::vector<int16_t>& data, int splen, int index);
    void convert(const std::string&name, const std::vector<uint16_t>& data, int splen, int index);
    void convert(const std::string&name, const std::vector<int32_t>& data, int splen, int index);
    void convert(const std::string&name, const std::vector<uint32_t>& data, int splen, int index);
    void convert(const std::string&name, const std::vector<int64_t>& data, int splen, int index);
    void convert(const std::string&name, const std::vector<uint64_t>& data, int splen, int index);
    void convert(const std::string&name, const std::vector<float>& data, int splen, int index);
    void convert(const std::string&name, const std::vector<double>& data, int splen, int index);
    void convert(const std::string&name, const std::vector<bool>& data, int splen, int index);
    void convert(const std::string&name, const std::vector<std::string>& data, int splen, int index);

    // base type set
    void convert(const std::string&name, const std::set<int16_t>& data, int splen, int index);
    void convert(const std::string&name, const std::set<uint16_t>& data, int splen, int index);
    void convert(const std::string&name, const std::set<int32_t>& data, int splen, int index);
    void convert(const std::string&name, const std::set<uint32_t>& data, int splen, int index);
    void convert(const std::string&name, const std::set<int64_t>& data, int splen, int index);
    void convert(const std::string&name, const std::set<uint64_t>& data, int splen, int index);
    void convert(const std::string&name, const std::set<float>& data, int splen, int index);
    void convert(const std::string&name, const std::set<double>& data, int splen, int index);
    void convert(const std::string&name, const std::set<bool>& data, int splen, int index);
    void convert(const std::string&name, const std::set<std::string>& data, int splen, int index);

    template <typename TYPE>
    void convert(const std::string&name, const std::vector<TYPE> &data, int splen, int index) {
        linefeed(index);
        std::string oldsep(_sep);
        //_ss<<std::string(splen, ' ')<<_key<<name<<_key<<_assign<<_vecb;
        if (!name.empty()) {
            _ss<<std::string(splen, ' ')<<_key<<name<<_key<<_assign<<_vecb;
        } else {
            _ss<<std::string(splen, ' ')<<_vecb;
        }
        for (size_t i=0; i<data.size(); ++i) {
            _sep=",";
            this->convert("", data[i], splen+space(), (int)i);
            _sep=oldsep;
        }
        _ss<<(_newline?"\n":"")<<std::string(splen, ' ')<<_vece;
    }

    template <typename TYPE>
    void convert(const std::string&name, const std::set<TYPE> &data, int splen, int index) {
        int i = 0;
        linefeed(index);
        std::string oldsep(_sep);
        //_ss<<std::string(splen, ' ')<<_key<<name<<_key<<_assign<<_vecb;
        if (!name.empty()) {
            _ss<<std::string(splen, ' ')<<_key<<name<<_key<<_assign<<_vecb;
        } else {
            _ss<<std::string(splen, ' ')<<_vecb;
        }
        for (typename std::set<TYPE>::const_iterator it=data.begin(); it!=data.end(); ++it) {
            _sep=",";
            this->convert("", *it, splen+space(), i++);
            _sep=oldsep;
        }
        _ss<<(_newline?"\n":"")<<std::string(splen, ' ')<<_vece;
    }

    template <typename TYPE>
    void convert(const std::string&name, const std::map<std::string,TYPE> &data, int splen, int index) {
        int i = 0;
        linefeed(index);
        std::string oldsep(_sep);
        if (!name.empty()) {
            _ss<<std::string(splen, ' ')<<_key<<name<<_key<<_assign<<"{";
        } else {
            _ss<<std::string(splen, ' ')<<"{";
        }
        for (typename std::map<std::string,TYPE>::const_iterator iter=data.begin(); iter!=data.end(); ++iter) {
            _sep=",";
            this->convert(iter->first, iter->second, splen+space(), i++);
            _sep=oldsep;
        }
        _ss<<(_newline?"\n":"")<<std::string(splen, ' ')<<"}";
    }

    template <typename KEYTYPE, typename TYPE>
    void convert(const std::string&name, const std::map<KEYTYPE, TYPE> &data, int splen, int index) {
        int i = 0;
        linefeed(index);
        std::string oldsep(_sep);
        if (!name.empty()) {
            _ss<<std::string(splen, ' ')<<_key<<name<<_key<<_assign<<"{";
        } else {
            _ss<<std::string(splen, ' ')<<"{";
        }
        for (typename std::map<KEYTYPE,TYPE>::const_iterator iter=data.begin(); iter!=data.end(); ++iter) {
            _sep=",";
            std::string _k = boost::lexical_cast<std::string>(iter->first);
            this->convert(_k, iter->second, splen+space(), i++);
            _sep=oldsep;
        }
        _ss<<(_newline?"\n":"")<<std::string(splen, ' ')<<"}";
    }

    template <typename TYPE>
    void convert(const std::string&name, const TYPE& data, int splen, int index) {
        linefeed(index);
        data.__struct_to_str(*this, name, splen);
    }
private:
    void linefeed(int index) {
        if (index>0) {
            _ss<<_sep;
        }
        if (_newline) {
            _ss<<'\n';
        }
    }
    template <typename TYPE>
    void base_convert(const std::string&name, const TYPE& data, int splen, int index) {
        linefeed(index);
        if (!name.empty()) {
            _ss<<std::string(splen, ' ')<<_key<<name<<_key<<_assign<<data;
        } else {
            _ss<<std::string(splen, ' ')<<data;
        }
    }
    template <typename TYPE>
    void base_vector(const std::string&name, const std::vector<TYPE>& data, int splen, int index) {
        linefeed(index);
        if (!name.empty()) {
            _ss<<std::string(splen, ' ')<<_key<<name<<_key<<_assign<<_vecb;
        } else {
            _ss<<std::string(splen, ' ')<<_vecb;
        }
        for (typename std::vector<TYPE>::const_iterator it=data.begin(); it!=data.end(); ++it) {
            if (it != data.begin()) {
                _ss<<',';
            }
            _ss<<*it;
        }
        _ss<<_vece;
    }
    template <typename TYPE>
    void base_set(const std::string&name, const std::set<TYPE>& data, int splen, int index) {
        linefeed(index);
        if (!name.empty()) {
            _ss<<std::string(splen, ' ')<<_key<<name<<_key<<_assign<<_vecb;
        } else {
            _ss<<std::string(splen, ' ')<<_vecb;
        }
        for (typename std::set<TYPE>::const_iterator it=data.begin(); it!=data.end(); ++it) {
            if (it != data.begin()) {
                _ss<<',';
            }
            _ss<<*it;
        }
        _ss<<_vece;
    }
private:
    bool _json;
    bool _newline;
    int  _space;
    std::string _vecb;  // json:[, cfg:(
    std::string _vece;  // json:], cfg:)
    std::string _key;   // json:", cfg:(empty)
    std::string _assign;// json::, cfg:=
    std::string _sep;   // json:,, cfg:;
    std::stringstream _ss;
};

}

#endif


jsonstrcfg.cpp json序列化反序列化定义


* Copyright (C) 2017 YY Inc. All rights reserved.
*
* Licensed 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 <json/json.h>

#include "jsoncfgstr.hpp"

namespace x2struct {

using namespace std;


JsonCfgStr::JsonCfgStr(bool isjson, bool newline, int splen)
    :XStr(isjson?"json":"config"),_json(isjson), _newline(newline),_space(splen)
{
    if (isjson) {
        _vecb = "[";
        _vece = "]";
        _key = "\"";
        _assign = ":";
        _sep = ",";
    } else {
        _vecb = "(";
        _vece = ")";
        _assign = "=";
        _sep = ";";
    }
}

JsonCfgStr::~JsonCfgStr()
{
}

void JsonCfgStr::begin(const string&root, int splen)
{
    if (root.empty()) {
        _ss<<string(splen, ' ')<<"{";
    } else {
        _ss<<string(splen, ' ')<<_key<<root<<_key<<_assign<<"{";
    }
}

void JsonCfgStr::end(const string&root, int splen)
{
    if (_newline) {
        _ss<<'\n';
    }
    _ss<<string(splen, ' ')<<"}";
}

int  JsonCfgStr::space()
{
    return _newline?_space:0;
}

string JsonCfgStr::toStr()const 
{
    return _ss.str();
}

void JsonCfgStr::convert(const string&name, int16_t data, int splen, int index)
{
    base_convert(name, data, splen, index);
}

void JsonCfgStr::convert(const string&name, uint16_t data, int splen, int index)
{
    base_convert(name, data, splen, index);
}

void JsonCfgStr::convert(const string&name, int32_t data, int splen, int index)
{
    base_convert(name, data, splen, index);
}

void JsonCfgStr::convert(const string&name, uint32_t data, int splen, int index)
{
    base_convert(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, int64_t data, int splen, int index)
{
    base_convert(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, uint64_t data, int splen, int index)
{
    base_convert(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, float data, int splen, int index)
{
    base_convert(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, double data, int splen, int index)
{
    base_convert(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, bool data, int splen, int index)
{
    base_convert(name, data?"true":"false", splen, index);
}

void JsonCfgStr::convert(const string&name, const string& data, int splen, int index)
{
    linefeed(index);
    if (_json) {
        _ss<<string(splen, ' ')<<_key<<name<<_key<<_assign<<Json::valueToQuotedString(data.c_str());
    } else {
        _ss<<string(splen, ' ')<<_key<<name<<_key<<_assign<<'"'<<data<<'"';
    }
}


// base type vector
void JsonCfgStr::convert(const std::string&name, const std::vector<int16_t>& data, int splen, int index)
{
    base_vector(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::vector<uint16_t>& data, int splen, int index)
{
    base_vector(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::vector<int32_t>& data, int splen, int index)
{
    base_vector(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::vector<uint32_t>& data, int splen, int index)
{
    base_vector(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::vector<int64_t>& data, int splen, int index)
{
    base_vector(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::vector<uint64_t>& data, int splen, int index)
{
    base_vector(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::vector<float>& data, int splen, int index)
{
    base_vector(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::vector<double>& data, int splen, int index)
{
    base_vector(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::vector<bool>& data, int splen, int index)
{
    base_vector(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::vector<std::string>& data, int splen, int index)
{
    linefeed(index);
    _ss<<std::string(splen, ' ')<<_key<<name<<_key<<_assign<<_vecb;
    for (typename std::vector<std::string>::const_iterator it=data.begin(); it!=data.end(); ++it) {
        if (it != data.begin()) {
            _ss<<',';
        }
        _ss<<'"'<<*it<<'"';
    }
    _ss<<_vece;
}


// base type set
void JsonCfgStr::convert(const std::string&name, const std::set<int16_t>& data, int splen, int index)
{
    base_set(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::set<uint16_t>& data, int splen, int index)
{
    base_set(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::set<int32_t>& data, int splen, int index)
{
    base_set(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::set<uint32_t>& data, int splen, int index)
{
    base_set(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::set<int64_t>& data, int splen, int index)
{
    base_set(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::set<uint64_t>& data, int splen, int index)
{
    base_set(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::set<float>& data, int splen, int index)
{
    base_set(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::set<double>& data, int splen, int index)
{
    base_set(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::set<bool>& data, int splen, int index)
{
    base_set(name, data, splen, index);
}

void JsonCfgStr::convert(const std::string&name, const std::set<std::string>& data, int splen, int index)
{
    linefeed(index);
    _ss<<std::string(splen, ' ')<<_key<<name<<_key<<_assign<<_vecb;
    for (typename std::set<std::string>::const_iterator it=data.begin(); it!=data.end(); ++it) {
        if (it != data.begin()) {
            _ss<<',';
        }
        _ss<<'"'<<*it<<'"';
    }
    _ss<<_vece;
}
}




第二种。实际上没做序列化定义,支撑任意类型的快速写入和取出,尤其应用在于单生产者、单消费者线程的无锁共享。怎么把它改造成rpc形式的序列化和反序列化,甚至支撑任意类型存储。可以使用avro特化函数。也可以借用redis队列协议即(数据类型+数据)。只是给个引子,怎么实现各位可以自己思考

.h

#ifndef __LOGBLOCKMANER_H__
#define __LOGBLOCKMANER_H__

#include <stdio.h>
class LogBlockManer
{
public:
	~LogBlockManer()
		{
		}
	LogBlockManer()
	{
		_blockSize = 1;
	}
private:
	
	struct __BlockNode
	{
		int seq;
		int w_offset;
		int r_offset;
		int memsize;
		char * memory;
		struct __BlockNode * next;

		__BlockNode()
		{
			seq = 0;
			w_offset = 0;
			r_offset = 0;
			memsize  = 0;
			memory = NULL;
			next = NULL;
		}

		void reset(int size)
		{
			w_offset = 0;
			r_offset = 0;
			memsize  = size;	
			next = NULL;
			return ;
		}
	};

	__BlockNode * _wrnode;
	__BlockNode * _rdnode;
	__BlockNode * _head;
	int           _blockSize;

	
	int           _threadmem;
public:
	int Init();
	int  writeLog(char * log,int size,__FileInfo *&file);
	bool readLog(char *& log,int &size,__FileInfo *&file);
	int  setThreadmemsize(int size);
};

#endif

.cpp
#include "LogBlockManer.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MEMSIZE 1024*1024

int LogBlockManer::writeLog(char * log,int size,__FileInfo *&file)
{
	static int int_size = sizeof(int);
	static int charpoint_size = sizeof(char*);
	if(_wrnode->w_offset + size + charpoint_size + int_size>= _wrnode->memsize)
	{
		if(!_wrnode->memory)
		{
			_wrnode->memory = new char[MEMSIZE];
			if(!_wrnode->memory)
			{
				return 0;
			}
			_wrnode->memsize = MEMSIZE;	
		}else
		{
			__BlockNode * node = new __BlockNode();
			if(!node)
			{			
			    return 0;
			}	
			node->memory = new char[MEMSIZE];
			if(!node->memory)
			{
		            delete node;
			    return 1;
			}			

		        _blockSize++;
		        _wrnode->next = node;
			_wrnode = node;	
			_wrnode->memsize = MEMSIZE;
		}
			
	}
		
	}
	
	memcpy((void*)(_wrnode->memory+_wrnode->w_offset),(void*)&file,charpoint_size);
	memcpy((void*)(_wrnode->memory+_wrnode->w_offset+charpoint_size),(void*)&size,int_size);
	memcpy((void*)(_wrnode->memory+_wrnode->w_offset+(charpoint_size+int_size)),(void*)log,size);
	_wrnode->w_offset += (size+int_size+charpoint_size);
	
	return 0;
}

bool LogBlockManer::readLog(char * & log,int & size,__FileInfo *&file)
{
	static int int_size2 = sizeof(int);
	static int charpoint_size = sizeof(char*);
	if(_rdnode->r_offset >= _rdnode->w_offset)
	{
		if(_rdnode != _wrnode)
		{
			__BlockNode * node = _rdnode;
			_rdnode = _rdnode->next;
			delete [] node->memory;
			delete node;
			
			if(_rdnode->r_offset >= _rdnode->w_offset)
			{
				return false;
			}
		}else
		{
			return false;
		}
	}
	memcpy((void*)&file,(void*)(_rdnode->memory + _rdnode->r_offset),charpoint_size);
	memcpy((void*)&size,(void*)(_rdnode->memory + _rdnode->r_offset + charpoint_size),int_size2);
	log = _rdnode->memory + (charpoint_size + int_size2+_rdnode->r_offset);
	_rdnode->r_offset += (size+charpoint_size+int_size2);
	return true;
}

int LogBlockManer::Init()
{
	_wrnode = new __BlockNode();
	if(!_wrnode)
	{
		return -1;
	}
	
	_head   = _wrnode;
	_rdnode = _wrnode;

	return 0;
}

int LogBlockManer::setThreadmemsize(int size)
{
	_threadmem = size;
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值