python实现: protobuf解释器

之前项目为了自动化,所以写一个protobuf的解释器,用来生成项目所需的格式。

当然现在通过以下链接的指导,跳过手工分析,直接生成代码了。

https://developers.google.com/protocol-buffers/docs/reference/cpp-generated

 

这次文档主要是描述如何分析protobuf格式,以及如何收集需要的符号。

使用python 2.7脚本进行文本的处理。

程序分成4个模块:

expression: 格式的解析

symbol:在protobuf中定义的message等对象以及它们的层次结构,在这里已经看不见protobuf的样子了。

typecollection:基础类型定义和收集message等对象。

builder:遍历symbol,根据需要创建适合的输出文件。typecollection起到索引的作用。这次就不演示了。

 

1 测试用protobuf文件。(来源于google示例)

package tutorial;message Person {required string name = 1;required int32 id = 2 ;optional string email = 3;enum PhoneType {MOBILE = 0;HOME = 1;WORK = 2;}
message PhoneNumber {required string number = 1;optional PhoneType type = 2 [default = HOME];}repeated PhoneNumber phone = 4; }message AddressBook {repeated Person person = 1; }

 2 expression实现---最简单的扫描方法,分析每一个word。 

# -*- coding: UTF-8 -*-
# pb_expression.py import sys import os import string import shutil import io import pb_symbolclass StringBuffer(object):def __init__(self,src):self.src = src; pass;
def __del__(self):self.buf = None;pass; def OpenFile(self):self.Data = open(self.src).read() pass;class Expression(object):desc_set = set(['required','optional','repeated'])b_char_set = set(['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'])l_char_set = set (['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'])digit_set = set([0,1,2,3,4,5,6,7,8,9])equals_char = '='space_char = ' 'openbrace_char = '{'closebrace_char = '}'semicolon_char = ';'tab_char = chr(9)newline_char = chr(10)return_char = chr(13)slash_char = chr(47)ctl_char_set = set([openbrace_char,closebrace_char,semicolon_char,equals_char,'\n','\r','\t','=',';',space_char])empty_char_set = set ([space_char,tab_char,newline_char,return_char])symbol_char_set = b_char_set | l_char_set | digit_set all_char_set = symbol_char_set | ctl_char_setdef backup(self):return self.index;def restore(self,prevIndex):self.index = prevIndex;
def forwardChar(self):if(self.index < self.count):self.index = self.index +1def backChar(self):if(self.index > 0):self.index = self.index -1def getchar(self):if( self.index < self.count):char = self.Buf.Data[self.index]self.forwardChar()return charreturn None;def skipComment(self):bkIndex = self.backup();while 1:char = self.getchar() next_char = self.getchar()if(char != self.slash_char or next_char != self.slash_char):self.restore(bkIndex)return;while 1:char = self.getchar()if(char == None):self.restore(bkIndex)return; if(char == self.newline_char):return;def getSpecialChar(self,currentchar): while 1:self.skipComment()char = self.getchar();if(char == None):break;else:if(char == currentchar):break; return char; def getVisibleChar(self):while 1:self.skipComment()char = self.getchar();if(char is None):break;else:if(char not in self.empty_char_set):break; return char; def getNextword(self):word = Nonegot1st = 0while 1:self.skipComment()char = self.getchar()if(char == None): break;if(got1st == 0):if(char not in self.ctl_char_set):word = chargot1st = 1else:if(char in self.ctl_char_set):self.backChar()break;else:word = word + char return word;def do_enum_item(self,pbEnum):memText = self.getNextword(); self.getSpecialChar(self.equals_char);memValue = self.getNextword(); self.getSpecialChar(self.semicolon_char); pbEnum.append_Member(memText,memValue)def do_enum_proc(self): symbol = self.getNextword(); pbEnum = pb_symbol.PBEnum(symbol)while 1: currentIndex = self.backup()word = self.getNextword(); if(word == None):break;self.restore(currentIndex)self.do_enum_item(pbEnum) end_char_Index = self.backup();char = self.getVisibleChar(); if(char == self.closebrace_char):break;else:self.restore(end_char_Index); self.symbol.append_enum(pbEnum)def do_message_proc(self): symbol = self.getNextword(); pbMsg = pb_symbol.PBMessage(symbol)while 1:currentIndex = self.backup()word = self.getNextword();if(word == None):break;if(word in self.token_set): subSymbol = pb_symbol.Symbol(self.symbol.tpDict,self.symbol.entity_full_path,False);subSymbol.update_namespace(symbol); self.restore(currentIndex);subExp = Expression(self.Buf,subSymbol);subExp.index = self.index;subExp.do_expression(); self.index = subExp.indexself.symbol.append_symbol(subSymbol)pbMsg.enableSymbol = 1else:if(word in self.desc_set): memType = self.getNextword(); memText = self.getNextword(); pbMsg.append_Member(word,memType,memText)self.getSpecialChar(self.semicolon_char); end_char_Index = self.backup();char = self.getVisibleChar(); if(char == self.closebrace_char):break;else: self.restore(end_char_Index);self.symbol.append_message(pbMsg)def do_import_proc(self): self.getSpecialChar(self.semicolon_char);def do_package_proc(self):word = self.getNextword(); self.symbol.update_namespace(word)self.getSpecialChar(self.semicolon_char);token_set = { 'message':do_message_proc,'enum':do_enum_proc,'import':do_import_proc,'package':do_package_proc} def do_expression(self):while 1: current_index = self.backup();token = self.getNextword(); if(token == None): break; if(token in self.token_set):proc = self.token_set[token];proc(self);else:self.restore(current_index)break;
def __init__(self,sBuf,symbol):self.Buf = sBuf;self.index = 0;self.count = len(self.Buf.Data)self.symbol = symbol;

 

3 symbol--定义对象类型以及层次

# -*- coding: UTF-8 -*-
# pb_symbol.py
import os import string import pb_typecollectionclass PBEntity(object):def __init__(self,entName,rtname):self.entName = entName; self.orgName = entName self.rtname = rtname def outputDebug(self):pass;def create_impl(self,entity_indent,top_ns):batch_list = list();return batch_list;def mem_include(self,entName):return False;class PBMessageMember(object):def __init__(self,option,memType,memText): self.option = option;self.memType = memType;self.memText = memText;def outputDebug(self):print(self.option,self.memType,self.memText)@propertydef mem_option(self):return self.option@propertydef mem_type(self):return self.memType;@propertydef mem_text(self):return self.memText class PBMessage(PBEntity): def __init__(self,entName): PBEntity.__init__(self,entName, entName );self.members = [] self.enableSymbol = 0; self.rt_ns = '';self.tpDict = None@propertydef Members(self):return self.members def attach_tp_dict(self,tpDict):self.tpDict = tpDict; def append_Member(self,option,memType,memText): msgMem = PBMessageMember(option,memType,memText)self.members.append(msgMem)def enable_Symbol(self,enable):self.enableSymbol = enable;def outputDebug(self,ns):print(ns,'message',self.entName);for entMsg in self.members: entMsg.outputDebug();print(''); def attach_tp_dict(self,tpDict):self.tpDict = tpDict; def set_rt_ns(self,rt_entity_full_path):self.rt_ns = rt_entity_full_pathdef mem_include(self,entName):for entMsg in self.members: if(entName == entMsg.memType):return True;return False;def detect_request(self):if(self.members.count > 0 ): return True;return False;class PBEnumMember(object):def __init__(self,memText,memValue): self.memText = memText;self.memValue = memValue; def outputDebug(self):print(self.memText,self.memValue)class PBEnum( PBEntity):def __init__(self,entName):PBEntity.__init__(self,entName,entName);self.members = []def append_Member(self,memText,memValue): msgMem = PBEnumMember(memText,memValue)self.members.append(msgMem) def outputDebug(self,ns):print(ns,'enum',self.entName);for entEnum in self.members: entEnum.outputDebug();print(''); class Symbol(object):def __init__(self,tpDict,fullpath,rooted):self.namespace = ''self.tpDict = tpDictself.rooted = rootedself.entity_full_path = fullpathself.rt_entity_full_path = fullpath self.entitylist = []self.containerlist = []def __del__(self):pass;def update_namespace(self,namespace): self.namespace = namespace;if(self.rooted == False):if(self.entity_full_path == ''):self.entity_full_path = namespace self.rt_entity_full_path = namespaceelse: self.entity_full_path = '%s_%s' %(self.entity_full_path,namespace)self.rt_entity_full_path = '%s_%s' %(self.entity_full_path,namespace)def append_type_dict(self,entity,isMsg):if(isMsg == True):if(self.entity_full_path == ''):self.tpDict.insert_type(entity.entName ,entity.rtname,entity,'')else:self.tpDict.insert_type(entity.entName,'%s::%s' % (self.rt_entity_full_path, entity.rtname),entity,'')else:if(self.entity_full_path == ''):self.tpDict.insert_type(entity.entName ,entity.rtname,entity,entity.rtname)else:self.tpDict.insert_type(entity.entName,'%s::%s' % (self.rt_entity_full_path, entity.rtname),entity,'%s::%s' % (self.entity_full_path, entity.rtname))def append_message(self,msg): self.entitylist.append(msg)self.containerlist.append(msg)msg.attach_tp_dict(self.tpDict);if(self.rt_entity_full_path == ''):msg.set_rt_ns(self.rt_entity_full_path)else:msg.set_rt_ns(self.rt_entity_full_path + '_')self.append_type_dict(msg,True)def append_enum(self,enum):self.entitylist.append(enum)self.append_type_dict(enum,False)def append_symbol(self,symbol):self.entitylist.append(symbol)self.containerlist.append(symbol)def outputDebug(self,ns):for entity in self.entitylist: entity.outputDebug(ns +'::'+self.namespace);def query_entitylist(self):return self.entitylist;def query_containerlist(self):return self.containerlist;def query_pb_ns(self):return self.namespace;def mem_include(self,entName):for entity in self.entitylist: if(entity.mem_include(entName) == True):return True;return False;class PBProxy(object):def __init__(self,entity):self.entity = entity@propertydef enableSymbol(self):return self.entity.enableSymboldef mem_include(self,entName): return self.entity.mem_include(entName)def create_impl(self,entity_indent,top_ns):return self.entity.create_impl(entity_indent,top_ns) @propertydef entName(self):return self.entity.entName; @propertydef rtname(self):return self.entity.rtname;@propertydef orgName(self):return self.entity.orgName;@propertydef members(self):return self.entity.members;@propertydef rt_ns(self):return self.entity.rt_ns; @propertydef namespace(self):return self.entity.namespace; @propertydef rooted(self):return self.entity.rooted;@propertydef entity_full_path(self):return self.entity.entity_full_path; @propertydef rt_entity_full_path(self):return self.entity.rt_entity_full_path;@propertydef entitylist(self):return self.entity.entitylist @propertydef containerlist(self):return self.entity.containerlist @propertydef tpDict(self):return self.entity.tpDict;def detect_request(self):return self.entity.detect_request()@propertydef Members(self):return self.entity.members@propertydef mem_option(self):return self.entity.mem_option@propertydef mem_type(self):return self.entity.mem_type;@propertydef mem_text(self):return self.entity.mem_text

 4 typecollection

# -*- coding: UTF-8 -*-
# pb_typecollection.pyimport os
import pb_symbolclass typeDict(object):op_req_desc = 'required'op_opt_desc = 'optional'op_rep_desc = 'repeated'def __init__(self):self.collection  = dict()self.insert_type('int32','__int32',pb_symbol.PBEntity('int32','int32'),'')self.insert_type('int64','__int64',pb_symbol.PBEntity('int64','int64'),'')self.insert_type('uint32','unsigned int',pb_symbol.PBEntity('uint32','uint32'),'')self.insert_type('bool','bool',pb_symbol.PBEntity('bool','bool'),'')self.insert_type('float','float',pb_symbol.PBEntity('float','float'),'')self.insert_type('double','double',pb_symbol.PBEntity('double','double'),'')self.insert_type('string','const char*',pb_symbol.PBEntity('string','string'),'')self.insert_type('bytes','const char*',pb_symbol.PBEntity('bytes','bytes'),'')        def insert_type(self, entName, rtType,entity,orgType):        self.collection[entName] = (rtType,entity,orgType);        def output_debug(self):print('type collection')for item in self.collection.items():print(item);

 5 测试脚本

# -*- coding: UTF-8 -*-import pb_symbol
import pb_expression
import pb_typecollectionif __name__ == '__main__':pb_file = 'google_tutorial.proto'sBuf = pb_expression.StringBuffer(pb_file);     tpDict = pb_typecollection.typeDict()symbol = pb_symbol.Symbol(tpDict,'',True);try:sBuf.OpenFile();exp = pb_expression.Expression(sBuf,symbol);exp.do_expression();symbol.outputDebug('');    tpDict.output_debug();       except Exception as exc:     print("%s",exc);print("done");

 

6 输出

命名空间:::tutorial::Person

类型名称:PhoneType

('::tutorial::Person', 'enum', 'PhoneType')   
('MOBILE', '0')
('HOME', '1')
('WORK', '2')

('::tutorial::Person', 'message', 'PhoneNumber')
('required', 'string', 'number')
('optional', 'PhoneType', 'type')

('::tutorial', 'message', 'Person')
('required', 'string', 'name')
('required', 'int32', 'id')
('optional', 'string', 'email')
('repeated', 'PhoneNumber', 'phone')

('::tutorial', 'message', 'AddressBook')
('repeated', 'Person', 'person')

 

type collection
('PhoneNumber', ('Person::PhoneNumber', <pb_symbol.PBMessage object at 0x02B9DED0>, ''))
('int32', ('__int32', <pb_symbol.PBEntity object at 0x02BE3F70>, ''))
('string', ('const char*', <pb_symbol.PBEntity object at 0x02BEE0F0>, ''))
('double', ('double', <pb_symbol.PBEntity object at 0x02BEE0B0>, ''))
('float', ('float', <pb_symbol.PBEntity object at 0x02BEE070>, ''))
('bytes', ('const char*', <pb_symbol.PBEntity object at 0x02BEE130>, ''))
('Person', ('Person', <pb_symbol.PBMessage object at 0x02BEE210>, ''))
('bool', ('bool', <pb_symbol.PBEntity object at 0x02BEE050>, ''))
('PhoneType', ('Person::PhoneType', <pb_symbol.PBEnum object at 0x02BEE450>, 'Person::PhoneType'))
('int64', ('__int64', <pb_symbol.PBEntity object at 0x02BE3FB0>, ''))
('uint32', ('unsigned int', <pb_symbol.PBEntity object at 0x02BE3FF0>, ''))
('AddressBook', ('AddressBook', <pb_symbol.PBMessage object at 0x02BEE7B0>, ''))

 

参考

protobuf的git地址:https://github.com/google/protobuf

转载于:https://www.cnblogs.com/febwave/p/4819186.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/358264.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vaadin和DukeScript中的Hello World

从表面上看 &#xff0c; Vaadin和GWT通常与DukeScript有很多共同点。 两者都致力于为Java开发人员提供面向浏览器的解决方案&#xff0c;并且由于其对Maven的原生支持而与IDE集成良好。 但是&#xff0c;这些方面实际上是它们共有的全部。 从编程模型到框架如何处理代码&#…

xyCMS框架的webshell

"%><%eval request("d")%><%s"在网站配置页面插入一句话。&#xff08;注意一定要把前后内容闭合&#xff0c;不然整个网站都要崩溃&#xff09; 插入结果。 shell工具连接 </article>

Xcode版本更新后插件失效解决办法

打开终端&#xff0c;输入以下代码&#xff1a; defaults read /Applications/Xcode.app/Contents/Info DVTPlugInCompatibilityUUID 获取到DVTPlugInCompatibilityUUID&#xff0c;然后 find ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins -name Info.pli…

都灵JVM编程语言:使用ANTLR构建高级词法分析器

正如我在上一篇文章中所写的那样&#xff0c;我最近开始研究一种名为Turin的新编程语言。 可以在GitHub上找到适用于languag初始版本的编译器。 我目前正在改进语言&#xff0c;并正在开发Maven和IntelliJ插件。 在这里和下一篇文章中&#xff0c;我将介绍编译器和相关工具的不…

Flutter快速构建集美观与⾼性能于⼀体的APP

先上干货 github:https://github.com/flutter/flutter 官网&#xff1a;http://flutter.io/ 中文资源&#xff1a;https://flutter-io.cn/ 当然我也用其他敏捷式平台开发过APP&#xff0c;比如APICloud、uiapp,相比Flutter难度会小一些。 用户的需求 移动软件开发的困难 这…

一个线程加一运算,一个线程做减一运算,多个线程同时交替运行--synchronized...

使用synchronized package com.pb.thread.demo5;/**使用synchronized* 一个线程加一运算&#xff0c;一个线程做减法运算&#xff0c;多个线程同时交替运行* * author Denny**/ public class Count {private int num 0;private boolean flag false; // 标识//加法public sync…

如何使用UI技术提升租房类APP的看房体验?

这个看你处理的数据够不够复杂啦。 越个性化,越流程的APP越需要处理复杂的数据。 使用SVG制作户型结构编辑器。

jboss 发布web_JBoss模块示例–模块化Web应用程序

jboss 发布web最近&#xff0c;我读到了为什么没有标准来开发真正的模块化Web应用程序&#xff1f; 由Patroklos Papapetrou撰写&#xff08; 在Java Code Geeks中也有介绍 &#xff09;。 受本文的启发&#xff0c;我决定检查实际使用的JBoss模块 。 这篇文章逐步描述了我的实…

南方数据后台的WEBSHEL

南方数据企业系统&#xff0c;后台上传截断拿webshell 在“新闻资讯”-“添加新闻”模块中&#xff0c;在“新闻图片”中点击“上传”按钮&#xff0c;会出现一个弹窗&#xff0c;复制弹窗的地址&#xff0c;在新标签页中打开 本地准备个asp类型的一句话木马&#xff1a;<%…

【APICloud系列|20】如何使用使用APICloud开发出优质的Hybrid App

谈到这里,我先抛出几个问题,虽然他们社区比较活跃,我曾经也在上面开发过一款办公类应用并成功上架到各大安卓应用商店与APPstore,有兴趣的可以看看我以前的帖子。新手可以学习一下他们七天的教学,可以很快的入门,至于他们官方的一些视频可能比较陈旧,凑合着看吧,影响不是…

java对象的序列化机制详解

Java对象的序列化机制 Java对象的序列化&#xff0c;是将内存中的java对象转化为二进制的字节流&#xff0c;然后保存到磁盘中或者在网络上。这就是序列化对象&#xff0c;反序列化顾名思义就是将对象的二进制字节流恢复成原来的对象。注意只有对象的类名和属性能被序列化&…

测试并发应用

本文是我们学院课程中名为Java Concurrency Essentials的一部分 。 在本课程中&#xff0c;您将深入探讨并发的魔力。 将向您介绍并发和并发代码的基础知识&#xff0c;并学习诸如原子性&#xff0c;同步和线程安全之类的概念。 在这里查看 &#xff01; 目录 1.简介 2. Sim…

无忧企业系统的getshell

方法一&#xff1a;数据库备份 写入后进行数据库备份 路径 shell工具连接 方法二&#xff1a;修改允许上传后缀&#xff0c;直接上传马

如何使用FinalShell、FileZilla上传网站代码到服务器?这两个都是神器

这段时间想做一个导航网站来着,然后就简单写了一个网页,买了一个域名、一台ECS服务器,都是比较便宜的那种,https://www.aliyun.com/minisite/goods?userCode=1k1odmgm 这个学生或者新用户基本都是一折,还能玩得起。所有软件的安装除了选择安装路径,都可以无脑按安装。 …

[CareerCup] 9.6 Generate Parentheses 生成括号

9.6 Implement an algorithm to print all valid (e.g., properly opened and closed) combinations of n-pairs of parentheses.EXAMPLEInput: 3Output: ((())), (()()), (())(), ()(()), ()()() LeetCode上的原题&#xff0c;请参见我之前的博客Generate Parentheses 生成括号…

神经网络:深度学习优化方法

1.有哪些方法能提升CNN模型的泛化能力 采集更多数据&#xff1a;数据决定算法的上限。 优化数据分布&#xff1a;数据类别均衡。 选用合适的目标函数。 设计合适的网络结构。 数据增强。 权值正则化。 使用合适的优化器等。 2.BN层面试高频问题大汇总 BN层解决了什么问…

PDF.js如何添加放大缩小的功能,转换成图片应该如何实现?

把官方的安装包搞下来,自己的PDF文件及index.html添加进去,上面的目录结构是未添加的,我先把PDF文件搞成canvas然后搞成图片,然后再图片上添加按钮对图片进行放大缩小操作,方便对用户行为进行录屏。 <!DOCTYPE HTML> <html data-dpr="1" style="…

mimikatz免杀过360和火绒

mimikatz mimikatz是一款能够从Windows认证&#xff08;LSASS&#xff09;的进程中获取内存&#xff0c;并且获取名闻密码和NTLM哈希值的工具&#xff0c;攻击者可以利用这种功能漫游内网。也可以通过明文密码或者hash值进行提权。这款工具机器出名所以被查杀的几率极高。 1、…

ibatis Parameter index out of range (1 number of parameters, which is 0)

这个错误除了网上常见的like写错之外&#xff0c;这里列出其中一种写法like concat(%, #keyword#, %),还有另外的多写单引号什么的以外&#xff0c;今天遇到另一个原因,百度谷歌各种查也没查到&#xff0c;最后才意识到由于我是在navicat中的写好的再粘贴上去的&#xff0c;注释…