ProtoBuf 源码简析

て烟熏妆下的殇ゞ 提交于 2019-12-01 02:07:04

ProtoBuf项目描述:
  Google Protocol Buffer简称protobuf,为高效的二进制序列化/反序列化协议(一般为google内部使用),不同于xml、json等,其更小巧、高效;avro、thrift等;
其可用于网络协议、数据存储等语言无关、平台无关、可扩展的序列化结构数据格式。只要按照特定条件可支持向前、向后兼容;目前提供了C++、Java、Python 
三种语言的 API,这样各语言可以相互序列化和反序列化数据信息(事实上也可以自定义实现其他语言的API接口)。
    
   在使用中,用户可根据自定义或引入数据结构(Message)文件*.proto;此后通过编译器protoc.exe编译该描述文件为指定语言的操作接口,而后将产生的操作接口文件
和libprotobuf.lib添加入项目中进行数据序列化和反序列化操作即可,产生的序列化后的信息可读性很差,此外反序列化也必须知道对应的数据结构描述文件*.proto,
否则无法正确地反序列化,也不再有意义,相对xml,json无法直接插入或修改数据信息内容;

  以下仅对C++相关进行分析;
  项目工程:
        gtest:google 白盒测试开源项目,主要用于单元测试,后面的gtest_main、tests项目;
        gtest_main:简单的对main函数以及testing::InitGoogleTest(&argc, argv);RUN_ALL_TESTS();封装的lib,这样其他测试工程只需要包含引入该库并集中精力在
        测试用例上;
        libprotobuf:protobuf基础工程库,主要实现;
        libprotobuf-lite:
        libprotobufc:对应protobuf的编译器封装为库,以支持c++、java、python语言对*.proto文件的编译为相应的接口API;
        lite-test:
        protoc:简单的控制台实现的protoc编译器,该编译器通过命令行参数传递对应的*.proto文件和编译输出接口API选项;依赖于libprotobuf、libprotobufc;
        test_plugin:
        tests:
        
    *.proto数据描述文件说明:
    
    protoc编译器命令行参数说明和生成文件API文件名说明:
    
    *.proto 文件编译后为*.pb.h以及*.pb.cc;
项目内容简析:  libprotobuf:protobuf基础工程库,内部主要实现编码和解码等相关操作。
    
        config.h:配置相关,事实上为声明宏hash_map、hash_set头文件以及编译宏HAVE_HASH_SET、HAVE_HASH_MAP;
        
        template_util.h :模板元编程相关的工具,模板、函数;主要包括:
            integral_constant、if_、type_equals_、and_、or_、true_、false_;
            
        type_traits.h :在template_util.h的基础上,定义了一系列类型特征萃取相关的模板类或函数如:is_xxx,has_xxx,remove_xxx;
        
        common.h:内部使用公共函数、基本类型,全局常量、用于当前库的工具模板辅助函数; 
            GOOGLE_DISALLOW_EVIL_CONSTRUCTORS:不允许赋值拷贝宏;
            LIBPROTOBUF_EXPORT/LIBPROTOC_EXPORT:导入导出宏;
            一系列标识库版本的宏、常量,格式:major * 10^6 + minor * 10^3 + micro,如:2005000;
            VersionString:整形转化为版本字符串;格式:major.minor.micro,如:2.5.0
            VerifyVersion:版本兼容性检定函数;
            重声明基本类型,便于统一处理以及定义了几种类型静态变量最大最小值;
            GOOGLE_ARRAYSIZE:安全的获取数组元素个数(若未对齐,则会提示除0警告);
            implicit_cast:隐式转换模板;类似于static_cast、const_cast的安全版本;
            down_cast:向下转换,由父类指针对象转型为某个子类,内部使用static_cast转型,在调试模式下时使用dynamic_cast进行验证;
            CompileAssert:编译时断言,结合GOOGLE_COMPILE_ASSERT宏,内部通过msg[-1或1]确定是否可通过编译,可能对浮点数0.0之类的存在歧义;
            scoped_ptr/scoped_array:指针包装,智能指针;
            LogLevel:日志级别,提供INFO、WARN、ERROR、FATAL几种严重级别;
            LogMessage:消息日志,记录、操作消息;
                LogMessage:构造函数传参为日志级别、文件名称、所在行;
                重载多个版本operator<<;
                Finish:完成操作,内部若为非FATAL日志,则将调用InitLogSilencerCountOnce,此外若无静默者·则调用log_handler_处理该日志,
                默认调用接口为DefaultLogHandler(默认向stderr输出,格式“[libprotobuf level filename:line] message ”),此外若为FATAL日志,
                则根据是否使用异常抛出FatalException类型对象异常或调用abort终止进程;
                level_:日志级别;
                filename_:文件名称;
                line_:所在行;
                message_:消息内容;
            LogFinisher:log日志完成者,实现了operator=,内部调用LogMessage的Finish函数;
            GOOGLE_LOG:log宏,封装LogFinisher作为工具封装;
            GOOGLE_LOG_IF:条件log宏;
            GOOGLE_CHECK_XXX:一系列检测宏,内部调用GOOGLE_LOG_IF(FATAL,...);
            CheckNotNull:非NULL检测以及宏GOOGLE_CHECK_NOTNULL;
            debug模式下的GOOGLE_DCHECK_XXX调试宏;
            SetLogHandler:设置日志控制器log_handler_,若参数为NULL则设置为NullLogHandler,其不处理日志信息,
            LogSilencer:日志静默者,跳过非FATAL日志,使得log_handler_控制器不处理日志;使用时可直接在某个函数点创建临时对象即可,在作用
            域内,产生的日志信息将会被“吸收”;作用域外则恢复到正常的日志处理;
            Closure:称为关闭、终止的基类,内部只提供了纯虚函数Run;
            FunctionClosureXXX/MethodClosureXXX:继承于Closure类,实现Run内部调用传入的函数并根据参数删除释放当前本类对象;前者主要传入普通
            或类的静态成员函数,后者主要处理类对象以及相应类的成员函数;目前仅实现了支持0,1,2个参数的继承类;
            NewCallback/NewPermanentCallback:分别重载了对应不同参数类型的模板帮助函数,内部通过new创建FunctionClosureXXX/MethodClosureXXX;
            前者创建了调用Run会自动删除对象;后者为永久对象,用户可根据需要某个时刻delete该对象;
            DoNothing:空函数操作;
            Mutex:锁,通过IMPL技巧实现,内部利用临界区实现锁机制,此外AssertHeld函数用以在调试模式下检测当前线程下是否为获取到锁的线程;
            MutexLock:自动锁,对Mutex的封装,此外重声明锁ReaderMutexLock、WriterMutexLock;
            MutexLockMaybe:同MutexLock,但更安全;
            IsStructurallyValidUTF8:检测是否包含UTF-8的字符编码;
            ghtonl:主机字节序转化为网络字节序,同htonl;
            ShutdownProtobufLibrary:关闭protobuf库,主要为执行关闭操作函数集vector<void (*)()>的shutdown_functions内容,释放shutdown_functions、
            shutdown_functions_mutex锁对象;
            OnShutdown:注册关闭库时被调用的函数,添加至shutdown_functions;
            FatalException:继承于std::exception,构造函数提供文件名称、所在行、消息内容,并添加filename、line、message操作方便获取相应成员变量值;
            
        platform_macros.h:跨平台相关的宏定义;
        
        atomicops.h:提供跨平台的原子操作,内部实现根据相应平台编译相应接口的实现,以下以X86 msvc编译器为例,将采用atomicops_internals_x86_msvc的实现;
            Atomic32/AtomicWord:原子类型重声明;
            NoBarrier_CompareAndSwap:内部调用InterlockedCompareExchange,实现原子的比较交换操作;
            NoBarrier_AtomicExchange:内部调用InterlockedExchange,实现原子指定值操作;
            NoBarrier_AtomicIncrement:内部调用InterlockedExchangeAdd,实现原子加操作,累加的数值为参数的2倍值;
            Barrier_AtomicIncrement:同NoBarrier_AtomicIncrement;、
            Acquire_CompareAndSwap:事实上内部调用NoBarrier_CompareAndSwap;
            Release_CompareAndSwap:事实上内部调用NoBarrier_CompareAndSwap;
            MemoryBarrier:内部调用MemoryBarrier,实现硬件防护,以防止CPU或编译器乱序执行;
            NoBarrier_Store:非防护设置,参数指针对象ptr设置值为value;
            Acquire_Store:内部调用NoBarrier_AtomicExchange;
            Release_Store:同NoBarrier_Store;
            NoBarrier_Load:获取当前参数值;
            Acquire_Load:获取临时参数值;
            Release_Load:获取MemoryBarrier防护后的当前参数值;
            
        once.h:主要封装初始化一次的操作;
            通过定义GOOGLE_PROTOBUF_DECLARE_ONCE宏原子变量以及初始化函数,当调用GoogleOnceInit时实现执行一次初始化函数;
            示例:void Init();GOOGLE_PROTOBUF_DECLARE_ONCE(once_init);void InitOnce(){GoogleOnceInit(&once_init,&Init);};任何多次调用InitOnce函数只会最终
            调用Init初始化函数一次;
            内部定义了三种原子状态:未初始化ONCE_STATE_UNINITIALIZED、正在执行初始化ONCE_STATE_EXECUTING_CLOSURE、已完成初始化ONCE_STATE_DONE;
            GoogleOnceInit:初始化一次函数,参数分别为原子、初始化函数;提供无参版本和重载模板一个参数的版本;函数内部调用Acquire_Load获取原子状态,此后根据
            状态处理创建FunctionClosure0执行GoogleOnceInitImpl;
            GoogleOnceInitImpl:内部处理原子状态并处理多线程下执行流程;若未初始化则设置原子为正在初始化并执行FunctionClosure0的Run函数,执行完成后设置原子
            为已完成初始化状态;若其他线程进入时,若此时仍为正在执行初始化,则循环查询原子状态并调用SchedYield放弃CPU时间片;
            
        strutil.h:字符、字符串工具函数;
            ascii_isalnum:ASCII码是否为a~z或A~Z或0~9的字符;
            ascii_isdigit:ASCII码是否为数字字符;
            HasPrefixString:原始字符串是否有指定的前缀字符串;
            StripPrefixString:获取剥去原始字符串中的指定前缀的字符串,否则为原始字符串;
            HasSuffixString:原始字符串是否有指定的后缀字符串;
            StripSuffixString:获取剥去原始字符串中的指定后缀的字符串,否则为原始字符串;
            StripString:查找指定字符串s中被匹配的模式字符串remove中出现的位置,并替换为字符replacewith;内部调用strpbrk实现查找匹配;
            LowerString:字符串小写化;
            UpperString:字符串大写化;
            StringReplace:相对StripString,其实现字符串分片替换为新的字符串,若参数replace_all为true,则全部替换,否则只替换第一次出现的;
            SplitStringUsing:对给定的模式字符串delim,匹配原始字符串full,并拆分至vector<string>* res中;
            SplitStringAllowEmpty:相对SplitStringUsing,其允许空原始字符串和传回空字符串;
            JoinStrings:提供两个版本,合并字符串和分隔符字符串合并,字符串间为分隔符字符串组合为返回字符串;
            UnescapeCEscapeSequences:转化字符串各字符为相应的ASCII码;
            UnescapeCEscapeString:同UnescapeCEscapeSequences;
            CEscapeString/CEscape:转化字符串,保存部分标识(目前\n, \r, \t, ", ', \以及不可打印的字符将被隐藏(保护));
            字符串与数值间的相互转化;
                strto32/strtou32/strto64/strtou64:字符串转数值(内部调用strtoXXX系列函数);
                FastXXXToBuffer:系列函数,数值转化为字符串,字符串右对齐;
                FastXXXToBufferLeft:系列函数,数值转化为字符串,字符串左对齐;
                SimpleItoa:重载版本,整型数值转字符串,参数为有符号时内部调用FastXXXToBuffer,无符号时调用FastXXXToBufferLeft;
                SimpleDtoa/SimpleFtoa:分别为双精度、单精度浮点转字符串;
                DoubleToBuffer/FloatToBuffer:双精度、单精度浮点转字符串;
                目前控制字符串转化最大长度为kDoubleToBufferSize(32位),kFloatToBufferSize(24位);
                NoLocaleStrtod:无区域化字符串转双精度浮点数;类似于strtod;
                
        stl_util.h:STL相关的部分辅助工具、函数;
            STLDeleteContainerPointers:模板实现,删除释放容器内指针对象资源,参数为容器收尾迭代器对象;
            STLStringResizeUninitialized:重置容器大小,针对string容器,内部调用resize;
            string_as_array:string字符串当前array使用,内部取string的begin地址位置;使用时示例;string str;string_as_array(&str)[i];
            个人认为与string的operator[]等价;
            STLDeleteElements:模板实现,内部调用STLDeleteContainerPointers,且调用容器对象的clear接口;释放容器内对象资源且清空容器;
            STLDeleteValues:模板实现,一般用在map或pair对的容器参数,以释放容器value值对应的对象内容,并调用clear清空容器;
            
        hash.h:封装实现内部使用的hash_map和hash_set;
            hash<key>:模板类,继承于std::hash_compare<key>;
            CstringLess:函数对象(仿函数),作为hash_compare<const char*, CstringLess>的operator<比较操作模板参数,其仅支持const char*参数(内部通过strcmp比较);
            hash<const char*>:hash模板特化版本,继承于std::hash_compare<const char*, CstringLess>;
            hash_map/hash_set:分别继承与hash_map/hash_set;对于非MSVC编译器,则采用的自己的实现,此外对hash<const char*>则使用result = 5 * result + *str;
            循环叠加的方式处理;
            hash<string>:hash模板特化版本;
            hash<pair<First, Second> >:针对pair的版本;
            streq:仿函数,实现比较const char*字符串相等操作,内部调用strcmp;
            
        maputil.h:map或hash_map辅助工具、函数,以下的map代表map或hash_map;
            FindWithDefault:查找map容器中指定key的value值,否则返回提供的默认值value;
            FindOrNull:查找map容器中指定key的value值地址,否则返回NULL;
            FindOrDie:查找map容器中指定key的value值地址,否则抛出FatalException异常或终止进程;
            FindPtrOrNull:查找map容器中指定key的value值,否则返回0;
            InsertOrUpdate:若map容器存在对应的key则更新,否则插入元素,返回值false表示更新,true为插入;
            InsertIfNotPresent:同InsertOrUpdate,不过存在对应的key时不再更新,返回值false为插入失败,true插入成功;
        
        stringprintf.h:字符串格式化输出、打印;
            StringPrintf:格式化输出字符串(内部通过调用StringAppendV实现);
            SStringPrintf:同StringPrintf,但是传入的参数dst会被清空;
            StringAppendV:格式化字符串,内部vsnprintf与va结合进行格式化,并采取基于堆和栈的方式实现长短字符串的格式化(栈最大大小kSpaceLength(1024字节));
            StringAppendF:同StringAppendV,内部不会清空参数dst,会追加格式化后的字符串;
            StringPrintfVector:打印格式化vector<string>数据容器,内部调用StringPrintf进行格式化;
            kStringPrintfVectorMaxArgs:StringPrintfVector中vector容器的最大参数(最大32个,若v容器大小大于该值将调用LOG(FATAL));
            string_printf_empty_block:保护StringPrintfVector打印,为空块;
            
        substitute.h:类似于stringprintf.h的字符串格式化,但是比stringprintf.h更加高效且使用方式上有所不同;
            SubstituteArg:格式化参数类,提供了多个支持基本数据类型的构造函数,此外提供提取转化后字符串data和字符串数据长度size接口,对于基本数据转换利用
            strutil.h中提供的快速转换,如FastInt32ToBuffer、FloatToBuffer等;
            Substitute:提供了支持至多9个参数的格式化字符串,参数为SubstituteArg类型或可转化为SubstituteArg类型的;此外格式化使用“$”后跟一个数字,
            该数字值为对应SubstituteArg参数,使用示例:
            string str;
            strings::SubstituteAndAppend(&str,"My name is $0 $1 and I am $2 years old.",first_name,last_name,age);事实上$后的数字可以一样;
            SubstituteAndAppend:同Substitute,但是会对格式化后的字符串数据对应参数output进行追加;
        
        zero_copy_stream.h:提供最小化数据流拷贝操作,主要提供ZeroCopyInputStream和ZeroCopyOutputStream抽象基类操作的接口,具体实现类位于
        zero_copy_stream_impl.h和zero_copy_stream_impl_lite.h中;
            此两个抽象基类操作接口如下(ZeroCopyOutputStream没有提供Skip接口):
            Next:获取数据流中的一块数据,参数data为指向的数据指针,size为获取的数据长度,返回值为false表示没有可读的数据或出现异常;
            BackUp:在调用Next后,可以回退内部数据指针索引位置,这样下一次调用Next时可以重新获取前一段数据;参数值不可大于早期Next得到的size长度;
            Skip:跳过部分数据流,返回false则表示已到数据流末尾或发生异常,为防止异常,可结合ByteCount和早期的Next确定是否会达到数据流末尾;
            ByteCount:获取当前数据流位置;
            
        zero_copy_stream_impl_lite.h:对zero_copy_stream.h中的抽象基类的实现,主要提供基于array、string的输入和输出流实现;
            ArrayInputStream:类array的输入流,继承于ZeroCopyInputStream;
                数据成员:
                    data_:指向uint8类型的array的数据指针;
                    size_:array数据的有效长度;
                    block_size_:每次调用获取Next获取的数据最大长度;
                    position_:当前数据的索引位置;
                    last_returned_size_:最后一次调用Next返回的数据长度;
                构造函数:参数data为指向数据array的指针(该数据array应在ArrayInputStream生命周期内是有效的),size为数据长度,block_size为Next获取的最大长度;
            ArrayOutputStream:类array的输出流,继承于ZeroCopyInputStream,操作大体同ArrayInputStream;
            StringOutputStream:支持string类型的输出流,继承于ZeroCopyInputStream;
                kMinimumSize:最小的new size大小,在处理Next操作中,调整目标string大小为kMinimumSize或2 * old_size或capacity()大小;
            CopyingInputStream:拷贝输入流;仅提供Read、Skip操作接口;
                Read:读取流中指定数据;参数buffer指向流数据针对,size数据流大小,返回值为读取到的字节数,返回0为读取到数据流尾,返回-1表示异常;
                Skip:跳过指定长度的数据流;返回值为跳过的实际长度;
            CopyingOutputStream:拷贝输出流,仅提供Write操作接口;
                Write:从给定buffer中读取size字节的数据至输出流;返回值true表示成功,false表示写入异常;
            CopyingInputStreamAdaptor:拷贝输入流适配器(事实上内部并非为zero-copy),继承于ZeroCopyInputStream,其以CopyingInputStream作为输入流对象;
                数据成员:
                    copying_stream_:CopyingInputStream类型的流对象指针;
                    owns_copying_stream_:是否是copying_stream_对象的拥有者,便以在释放的时候释放copying_stream_对象资源;
                    failed_:是否出现操作异常;
                    position_:当前数据流位置索引;
                    buffer_:读取到的数据流对象缓冲区;
                    buffer_size_:读取到的数据流对象缓冲区大小;
                    buffer_used_:调用Next最近一次的大小;
                    backup_bytes_:调用BackUp的回退字节数;
                成员函数:
                    构造函数,参数copying_stream为CopyingInputStream类型的流对象指针,block_size为数据缓冲区大小以初始化
                    buffer_size_(若为<0则为默认大小kDefaultBlockSize(8192));
                    SetOwnsCopyingStream:设置是否为copying_stream_对象的拥有者;
                    AllocateBufferIfNeeded:分配为buffer_size_大小的buffer_缓冲区;
                    FreeBuffer:释放buffer_缓冲区资源;
                    此外Next、BackUp、Skip、ByteCount为ZeroCopyInputStream的接口实现;
            CopyingOutputStreamAdaptor:拷贝输出流适配器(事实上内部并非为zero-copy),继承于ZeroCopyInputStream,其以CopyingOutputStream作为输出流对象;
                数据成员:
                    copying_stream_:CopyingOutputStream类型的流对象指针;
                    owns_copying_stream_:是否是copying_stream_对象的拥有者,便以在释放的时候释放copying_stream_对象资源;
                    failed_:是否出现操作异常;
                    position_:当前数据流位置索引;
                    buffer_:读取到的数据流对象缓冲区;
                    buffer_size_:读取到的数据流对象缓冲区大小;
                    buffer_used_:调用Next最近一次的大小;
                成员函数:
                    构造函数,参数copying_stream为CopyingOutputStream类型的流对象指针,block_size为数据缓冲区大小以初始化
                    buffer_size_(若为<0则为默认大小kDefaultBlockSize(8192));
                    SetOwnsCopyingStream:设置是否为copying_stream_对象的拥有者;
                    Flush:调用底层刷新写入数据至输出流;
                    AllocateBufferIfNeeded:分配为buffer_size_大小的buffer_缓冲区;
                    FreeBuffer:释放buffer_缓冲区资源;
                    WriteBuffer:写入当前buffer_used_大小的数据至输出缓冲区数据;
                
        zero_copy_stream_impl.h:对zero_copy_stream.h中的抽象基类的实现,主要实现File、stream、Concatenating、Limiting等几种流实现;
            FileInputStream:文件描述的读操作类,继承于ZeroCopyInputStream;
                先介绍CopyingFileInputStream:文件输入流类,继承于CopyingInputStream,实现读取文件数据;
                    数据成员:
                        file_:文件描述符或文件句柄;
                        close_on_delete_:关闭时,是否释放、删除文件描述对象;
                        is_closed_:是否已关闭;
                        errno_:IO操作错误码;
                        previous_seek_failed_:最近一次seek是否失败;
                    成员函数:
                        构造函数参数为文件描述符或文件句柄
                        Close:关闭文件描述符或文件句柄;
                        SetCloseOnDelete:设置关闭操作时,自动释放、文件描述对象;
                        GetErrno:获取IO操作错误码;
                        此外Read、Skip为CopyingInputStream类的实现接口,实现文件的读取和跳过指定字节数的操作;
                数据成员:
                    copying_input_:CopyingFileInputStream类型的输入流对象;
                    impl_:CopyingInputStreamAdaptor类型的输入流对象适配器,作为流输入对象的实现类;
                成员函数:
                    构造函数参数file_descriptor文件描述初始化copying_output_,其与block_size输入流块大小初始化impl_;
                    Close:关闭文件描述并刷新缓冲区,内部调用copying_input_的Close函数;
                    SetCloseOnDelete:设置关闭操作时,自动释放、文件描述对象,内部调用copying_input_的SetCloseOnDelete函数;
                    GetErrno:获取IO操作错误码,内部调用copying_input_的GetErrno函数;
                    此外Next、BackUp、Skip、ByteCount均内部调用impl_相应接口实现;
            FileOutputStream:文件描述的写操作类,继承于ZeroCopyOutputStream,接口实现与FileInputStream相似;
                增加了Flush接口以刷新输出流,无Skip接口;
            IstreamInputStream:用以对C++输入流操作,继承于ZeroCopyInputStream;同FileInputStream,只是操作构造函数为istream的对象;
                其内部读输入,使用istream的read、gcount、fail、eof接口操作;
            OstreamOutputStream:用以对C++输出流操作,继承于ZeroCopyOutputStream,同FileOutputStream,只是操作构造函数为ostream的对象;
                其内部写输出,使用ostream的write、good接口操作;
            ConcatenatingInputStream:处理多个ZeroCopyInputStream输入流的stream对象操作,继承于ZeroCopyInputStream;
                构造函数streams为ZeroCopyInputStream类型的指针数组,count为数组大小;
            LimitingInputStream:处理受限字节的输入流,,继承于ZeroCopyInputStream;
                构造函数input为ZeroCopyInputStream类型的指针对象,limit为字节上限;
            ConcatenatingInputStream与LimitingInputStream仅为其他stream对象的包装而已;

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!