remove lpeg & pbc

This commit is contained in:
云风
2012-09-04 11:25:10 +08:00
parent eba15c820f
commit 28dc8403a1
42 changed files with 0 additions and 13225 deletions

View File

@@ -13,8 +13,6 @@ all : \
service/connection.so \
client \
lualib/socket.so \
lualib/lpeg.so \
lualib/protobuf.so \
lualib/int64.so \
service/master.so \
service/multicast.so \
@@ -69,27 +67,6 @@ service/connection.so : connection/connection.c connection/main.c
lualib/socket.so : connection/lua-socket.c
gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src -Iconnection
lualib/lpeg.so : lpeg/lpeg.c
gcc $(CFLAGS) $(SHARED) -O2 $^ -o $@ -Ilpeg
PROTOBUFSRC = \
lua-protobuf/context.c \
lua-protobuf/varint.c \
lua-protobuf/array.c \
lua-protobuf/pattern.c \
lua-protobuf/register.c \
lua-protobuf/proto.c \
lua-protobuf/map.c \
lua-protobuf/alloc.c \
lua-protobuf/rmessage.c \
lua-protobuf/wmessage.c \
lua-protobuf/bootstrap.c \
lua-protobuf/stringpool.c \
lua-protobuf/decode.c
lualib/protobuf.so : $(PROTOBUFSRC) lua-protobuf/pbc-lua.c
gcc $(CFLAGS) $(SHARED) -O2 $^ -o $@
lualib/int64.so : lua-int64/int64.c
gcc $(CFLAGS) $(SHARED) -O2 $^ -o $@

View File

@@ -1,77 +0,0 @@
HISTORY for LPeg 0.10
* Changes from version 0.9 to 0.10
-------------------------------
+ backtrack stack has configurable size
+ better error messages
+ Notation for non-terminals in 're' back to A instead o <A>
+ experimental look-behind pattern
+ support for external extensions
+ works with Lua 5.2
+ consumes less C stack
- "and" predicates do not keep captures
* Changes from version 0.8 to 0.9
-------------------------------
+ The accumulator capture was replaced by a fold capture;
programs that used the old 'lpeg.Ca' will need small changes.
+ Some support for character classes from old C locales.
+ A new named-group capture.
* Changes from version 0.7 to 0.8
-------------------------------
+ New "match-time" capture.
+ New "argument capture" that allows passing arguments into the pattern.
+ Better documentation for 're'.
+ Several small improvements for 're'.
+ The 're' module has an incompatibility with previous versions:
now, any use of a non-terminal must be enclosed in angle brackets
(like <B>).
* Changes from version 0.6 to 0.7
-------------------------------
+ Several improvements in module 're':
- better documentation;
- support for most captures (all but accumulator);
- limited repetitions p{n,m}.
+ Small improvements in efficiency.
+ Several small bugs corrected (special thanks to Hans Hagen
and Taco Hoekwater).
* Changes from version 0.5 to 0.6
-------------------------------
+ Support for non-numeric indices in grammars.
+ Some bug fixes (thanks to the luatex team).
+ Some new optimizations; (thanks to Mike Pall).
+ A new page layout (thanks to Andre Carregal).
+ Minimal documentation for module 're'.
* Changes from version 0.4 to 0.5
-------------------------------
+ Several optimizations.
+ lpeg.P now accepts booleans.
+ Some new examples.
+ A proper license.
+ Several small improvements.
* Changes from version 0.3 to 0.4
-------------------------------
+ Static check for loops in repetitions and grammars.
+ Removed label option in captures.
+ The implementation of captures uses less memory.
* Changes from version 0.2 to 0.3
-------------------------------
+ User-defined patterns in Lua.
+ Several new captures.
* Changes from version 0.1 to 0.2
-------------------------------
+ Several small corrections.
+ Handles embedded zeros like any other character.
+ Capture "name" can be any Lua value.
+ Unlimited number of captures.
+ Match gets an optional initial position.
(end of HISTORY)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +0,0 @@
/*
** $Id: lpeg.h,v 1.1 2009/12/23 16:15:36 roberto Exp $
** LPeg - PEG pattern matching for Lua
** Copyright 2009, Lua.org & PUC-Rio (see 'lpeg.html' for license)
** written by Roberto Ierusalimschy
*/
#ifndef lpeg_h
#define lpeg_h
#include "lua.h"
#define KEYNEWPATT "lpeg.newpf"
/*
** type of extension functions that define new "patterns" for LPEG
** It should return the new current position or NULL if match fails
*/
typedef const char *(*PattFunc) (const char *s, /* current position */
const char *e, /* string end */
const char *o, /* string start */
const void *ud); /* user data */
/*
** function to create new patterns based on 'PattFunc' functions.
** This function is available at *registry[KEYNEWPATT]. (Notice
** the extra indirection; the userdata at the registry points to
** a variable that points to the function. In ANSI C a void* cannot
** point to a function.)
*/
typedef void (*Newpf) (lua_State *L,
PattFunc f, /* pattern */
const void *ud, /* (user) data to be passed to 'f' */
size_t l); /* size of data to be passed to 'f' */
#endif

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -1,42 +0,0 @@
LIBNAME = lpeg
LUADIR = /usr/include/lua5.1/
COPT = -O2 -DNDEBUG
CWARNS = -Wall -Wextra -pedantic \
-Waggregate-return \
-Wbad-function-cast \
-Wcast-align \
-Wcast-qual \
-Wdeclaration-after-statement \
-Wdisabled-optimization \
-Wmissing-prototypes \
-Wnested-externs \
-Wpointer-arith \
-Wshadow \
-Wsign-compare \
-Wstrict-prototypes \
-Wundef \
-Wwrite-strings \
# -Wunreachable-code \
CFLAGS = $(CWARNS) $(COPT) -ansi -I$(LUADIR)
CC = gcc
# For Linux
DLLFLAGS = -shared -fpic
ENV =
# For Mac OS
# ENV = MACOSX_DEPLOYMENT_TARGET=10.4
# DLLFLAGS = -bundle -undefined dynamic_lookup
lpeg.so: lpeg.o
env $(ENV) $(CC) $(DLLFLAGS) lpeg.o -o lpeg.so
lpeg.o: makefile lpeg.c lpeg.h
test: test.lua re.lua lpeg.so
test.lua

View File

@@ -1,486 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>LPeg.re - Regex syntax for LPEG</title>
<link rel="stylesheet"
href="http://www.inf.puc-rio.br/~roberto/lpeg/doc.css"
type="text/css"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<!-- $Id: re.html,v 1.17 2011/01/10 15:08:06 roberto Exp $ -->
<div id="container">
<div id="product">
<div id="product_logo">
<a href="http://www.inf.puc-rio.br/~roberto/lpeg/">
<img alt="LPeg logo" src="lpeg-128.gif"/>
</a>
</div>
<div id="product_name"><big><strong>LPeg.re</strong></big></div>
<div id="product_description">
Regex syntax for LPEG
</div>
</div> <!-- id="product" -->
<div id="main">
<div id="navigation">
<h1>re</h1>
<ul>
<li><a href="#basic">Basic Constructions</a></li>
<li><a href="#func">Functions</a></li>
<li><a href="#ex">Some Examples</a></li>
<li><a href="#license">License</a></li>
</ul>
</li>
</ul>
</div> <!-- id="navigation" -->
<div id="content">
<h2><a name="basic"></a>The <code>re</code> Module</h2>
<p>
The <code>re</code> module
(provided by file <code>re.lua</code> in the distribution)
supports a somewhat conventional regex syntax
for pattern usage within <a href="lpeg.html">LPeg</a>.
</p>
<p>
The next table summarizes <code>re</code>'s syntax.
A <code>p</code> represents an arbitrary pattern;
<code>num</code> represents a number (<code>[0-9]+</code>);
<code>name</code> represents an identifier
(<code>[a-zA-Z][a-zA-Z0-9_]*</code>).
Constructions are listed in order of decreasing precedence.
<table border="1">
<tbody><tr><td><b>Syntax</b></td><td><b>Description</b></td></tr>
<tr><td><code>( p )</code></td> <td>grouping</td></tr>
<tr><td><code>'string'</code></td> <td>literal string</td></tr>
<tr><td><code>"string"</code></td> <td>literal string</td></tr>
<tr><td><code>[class]</code></td> <td>character class</td></tr>
<tr><td><code>.</code></td> <td>any character</td></tr>
<tr><td><code>%name</code></td>
<td>pattern <code>defs[name]</code> or a pre-defined pattern</td></tr>
<tr><td><code>name</code></td><td>non terminal</td></tr>
<tr><td><code>&lt;name&gt;</code></td><td>non terminal</td></tr>
<tr><td><code>{}</code></td> <td>position capture</td></tr>
<tr><td><code>{ p }</code></td> <td>simple capture</td></tr>
<tr><td><code>{: p :}</code></td> <td>anonymous group capture</td></tr>
<tr><td><code>{:name: p :}</code></td> <td>named group capture</td></tr>
<tr><td><code>{~ p ~}</code></td> <td>substitution capture</td></tr>
<tr><td><code>=name</code></td> <td>back reference
</td></tr>
<tr><td><code>p ?</code></td> <td>optional match</td></tr>
<tr><td><code>p *</code></td> <td>zero or more repetitions</td></tr>
<tr><td><code>p +</code></td> <td>one or more repetitions</td></tr>
<tr><td><code>p^num</code></td> <td>exactly <code>n</code> repetitions</td></tr>
<tr><td><code>p^+num</code></td>
<td>at least <code>n</code> repetitions</td></tr>
<tr><td><code>p^-num</code></td>
<td>at most <code>n</code> repetitions</td></tr>
<tr><td><code>p -&gt; 'string'</code></td> <td>string capture</td></tr>
<tr><td><code>p -&gt; "string"</code></td> <td>string capture</td></tr>
<tr><td><code>p -&gt; {}</code></td> <td>table capture</td></tr>
<tr><td><code>p -&gt; name</code></td> <td>function/query/string capture
equivalent to <code>p / defs[name]</code></td></tr>
<tr><td><code>p =&gt; name</code></td> <td>match-time capture
equivalent to <code>lpeg.Cmt(p, defs[name])</code></td></tr>
<tr><td><code>& p</code></td> <td>and predicate</td></tr>
<tr><td><code>! p</code></td> <td>not predicate</td></tr>
<tr><td><code>p1 p2</code></td> <td>concatenation</td></tr>
<tr><td><code>p1 / p2</code></td> <td>ordered choice</td></tr>
<tr><td>(<code>name &lt;- p</code>)<sup>+</sup></td> <td>grammar</td></tr>
</tbody></table>
<p>
Any space appearing in a syntax description can be
replaced by zero or more space characters and Lua-style comments
(<code>--</code> until end of line).
</p>
<p>
Character classes define sets of characters.
An initial <code>^</code> complements the resulting set.
A range <em>x</em><code>-</code><em>y</em> includes in the set
all characters with codes between the codes of <em>x</em> and <em>y</em>.
A pre-defined class <code>%</code><em>name</em> includes all
characters of that class.
A simple character includes itself in the set.
The only special characters inside a class are <code>^</code>
(special only if it is the first character);
<code>]</code>
(can be included in the set as the first character,
after the optional <code>^</code>);
<code>%</code> (special only if followed by a letter);
and <code>-</code>
(can be included in the set as the first or the last character).
</p>
<p>
Currently the pre-defined classes are similar to those from the
Lua's string library
(<code>%a</code> for letters,
<code>%A</code> for non letters, etc.).
There is also a class <code>%nl</code>
containing only the newline character,
which is particularly handy for grammars written inside long strings,
as long strings do not interpret escape sequences like <code>\n</code>.
</p>
<h2><a name="func">Functions</a></h2>
<h3><code>re.compile (string, [, defs])</code></h3>
<p>
Compiles the given string and
returns an equivalent LPeg pattern.
The given string may define either an expression or a grammar.
The optional <code>defs</code> table provides extra Lua values
to be used by the pattern.
</p>
<h3><code>re.find (subject, pattern [, init])</code></h3>
<p>
Searches the given pattern in the given subject.
If it finds a match,
returns the index where this occurrence starts,
plus the captures made by the pattern (if any).
Otherwise, returns nil.
</p>
<p>
An optional numeric argument <code>init</code> makes the search
starts at that position in the subject string.
As usual in Lua libraries,
a negative value counts from the end.
</p>
<h3><code>re.match (subject, pattern)</code></h3>
<p>
Matches the given pattern against the given subject.
</p>
<h3><code>re.updatelocale ()</code></h3>
<p>
Updates the pre-defined character classes to the current locale.
</p>
<h2><a name="ex">Some Examples</a></h2>
<h3>A complete simple program</h3>
<p>
The next code shows a simple complete Lua program using
the <code>re</code> module:
</p>
<pre class="example">
local re = require"re"
-- find the position of the first number in a string
print(re.find("the number 423 is odd", "[0-9]+")) --&gt; 12
-- similar, but also captures (and returns) the number
print(re.find("the number 423 is odd", "{[0-9]+}")) --&gt; 12 423
-- returns all words in a string
print(re.match("the number 423 is odd", "({%a+} / .)*"))
--&gt; the number is odd
</pre>
<h3>Balanced parentheses</h3>
<p>
The following call will produce the same pattern produced by the
Lua expression in the
<a href="lpeg.html#balanced">balanced parentheses</a> example:
</p>
<pre class="example">
b = re.compile[[ balanced &lt;- "(" ([^()] / balanced)* ")" ]]
</pre>
<h3>String reversal</h3>
<p>
The next example reverses a string:
</p>
<pre class="example">
rev = re.compile[[ R &lt;- (!.) -&gt; '' / ({.} R) -&gt; '%2%1']]
print(rev:match"0123456789") --&gt; 9876543210
</pre>
<h3>CSV decoder</h3>
<p>
The next example replicates the <a href="lpeg.html#CSV">CSV decoder</a>:
</p>
<pre class="example">
record = re.compile[[
record &lt;- ( field (',' field)* ) -&gt; {} (%nl / !.)
field &lt;- escaped / nonescaped
nonescaped &lt;- { [^,"%nl]* }
escaped &lt;- '"' {~ ([^"] / '""' -&gt; '"')* ~} '"'
]]
</pre>
<h3>Lua's long strings</h3>
<p>
The next example matches Lua long strings:
</p>
<pre class="example">
c = re.compile([[
longstring &lt;- ('[' {:eq: '='* :} '[' close) -&gt; void
close &lt;- ']' =eq ']' / . close
]], {void = function () end})
print(c:match'[==[]]===]]]]==]===[]') --&gt; 17
</pre>
<h3>Abstract Syntax Trees</h3>
<p>
This example shows a simple way to build an
abstract syntax tree (AST) for a given grammar.
To keep our example simple,
let us consider the following grammar
for lists of names:
</p>
<pre class="example">
p = re.compile[[
listname &lt;- (name s)*
name &lt;- [a-z][a-z]*
s &lt;- %s*
]]
</pre>
<p>
Now, we will add captures to build a corresponding AST.
As a first step, the pattern will build a table to
represent each non terminal;
terminals will be represented by their corresponding strings:
</p>
<pre class="example">
c = re.compile[[
listname &lt;- (name s)* -&gt; {}
name &lt;- {[a-z][a-z]*} -&gt; {}
s &lt;- %s*
]]
</pre>
<p>
Now, a match against <code>"hi hello bye"</code>
results in the table
<code>{{"hi"}, {"hello"}, {"bye"}}</code>.
</p>
<p>
For such a simple grammar,
this AST is more than enough;
actually, the tables around each single name
are already overkilling.
More complex grammars,
however, may need some more structure.
Specifically,
it would be useful if each table had
a <code>tag</code> field telling what non terminal
that table represents.
We can add such a tag using
<a href="lpeg.html/#cap-g">named group captures</a>:
</p>
<pre class="example">
x = re.compile[[
listname <- ({:tag: '' -> 'list':} (name s)*) -> {}
name <- ({:tag: '' -> 'id':} {[a-z][a-z]*}) -> {}
s <- ' '*
]]
</pre>
<p>
With these group captures,
a match against <code>"hi hello bye"</code>
results in the following table:
</p>
<pre class="example">
{tag="list",
{tag="id", "hi"},
{tag="id", "hello"},
{tag="id", "bye"}
}
</pre>
<h3>Indented blocks</h3>
<p>
This example breaks indented blocks into tables,
respecting the indentation:
</p>
<pre class="example">
p = re.compile[[
block &lt;- ({:ident:' '*:} line
((=ident !' ' line) / &(=ident ' ') block)*) -&gt; {}
line &lt;- {[^%nl]*} %nl
]]
</pre>
<p>
As an example,
consider the following text:
</p>
<pre class="example">
t = p:match[[
first line
subline 1
subline 2
second line
third line
subline 3.1
subline 3.1.1
subline 3.2
]]
</pre>
<p>
The resulting table <code>t</code> will be like this:
</p>
<pre class="example">
{'first line'; {'subline 1'; 'subline 2'; ident = ' '};
'second line';
'third line'; { 'subline 3.1'; {'subline 3.1.1'; ident = ' '};
'subline 3.2'; ident = ' '};
ident = ''}
</pre>
<h3>Macro expander</h3>
<p>
This example implements a simple macro expander.
Macros must be defined as part of the pattern,
following some simple rules:
</p>
<pre class="example">
p = re.compile[[
text &lt;- {~ item* ~}
item &lt;- macro / [^()] / '(' item* ')'
arg &lt;- ' '* {~ (!',' item)* ~}
args &lt;- '(' arg (',' arg)* ')'
-- now we define some macros
macro &lt;- ('apply' args) -&gt; '%1(%2)'
/ ('add' args) -&gt; '%1 + %2'
/ ('mul' args) -&gt; '%1 * %2'
]]
print(p:match"add(mul(a,b), apply(f,x))") --&gt; a * b + f(x)
</pre>
<p>
A <code>text</code> is a sequence of items,
wherein we apply a substitution capture to expand any macros.
An <code>item</code> is either a macro,
any character different from parentheses,
or a parenthesized expression.
A macro argument (<code>arg</code>) is a sequence
of items different from a comma.
(Note that a comma may appear inside an item,
e.g., inside a parenthesized expression.)
Again we do a substitution capture to expand any macro
in the argument before expanding the outer macro.
<code>args</code> is a list of arguments separated by commas.
Finally we define the macros.
Each macro is a string substitution;
it replaces the macro name and its arguments by its corresponding string,
with each <code>%</code><em>n</em> replaced by the <em>n</em>-th argument.
</p>
<h3>Patterns</h3>
<p>
This example shows the complete syntax
of patterns accepted by <code>re</code>.
</p>
<pre class="example">
p = [=[
pattern &lt;- exp !.
exp &lt;- S (alternative / grammar)
alternative &lt;- seq ('/' S seq)*
seq &lt;- prefix*
prefix &lt;- '&amp;' S prefix / '!' S prefix / suffix
suffix &lt;- primary S (([+*?]
/ '^' [+-]? num
/ '-&gt;' S (string / '{}' / name)
/ '=&gt;' S name) S)*
primary &lt;- '(' exp ')' / string / class / defined
/ '{:' (name ':')? exp ':}'
/ '=' name
/ '{}'
/ '{~' exp '~}'
/ '{' exp '}'
/ '.'
/ name S !arrow
/ '&lt;' name '&gt;' -- old-style non terminals
grammar &lt;- definition+
definition &lt;- name S arrow exp
class &lt;- '[' '^'? item (!']' item)* ']'
item &lt;- defined / range / .
range &lt;- . '-' [^]]
S &lt;- (%s / '--' [^%nl]*)* -- spaces and comments
name &lt;- [A-Za-z][A-Za-z0-9_]*
arrow &lt;- '&lt;-'
num &lt;- [0-9]+
string &lt;- '"' [^"]* '"' / "'" [^']* "'"
defined &lt;- '%' name
]=]
print(re.match(p, p)) -- a self description must match itself
</pre>
<h2><a name="license">License</a></h2>
<p>
Copyright &copy; 2008-2010 Lua.org, PUC-Rio.
</p>
<p>
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"),
to deal in the Software without restriction,
including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software,
and to permit persons to whom the Software is
furnished to do so,
subject to the following conditions:
</p>
<p>
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
</p>
<p>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
</p>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<p><small>
$Id: re.html,v 1.17 2011/01/10 15:08:06 roberto Exp $
</small></p>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View File

@@ -1,248 +0,0 @@
-- $Id: re.lua,v 1.39 2010/11/04 19:44:18 roberto Exp $
-- imported functions and modules
local tonumber, type, print, error = tonumber, type, print, error
local setmetatable = setmetatable
local m = require"lpeg"
-- 'm' will be used to parse expressions, and 'mm' will be used to
-- create expressions; that is, 're' runs on 'm', creating patterns
-- on 'mm'
local mm = m
-- pattern's metatable
local mt = getmetatable(mm.P(0))
-- No more global accesses after this point
local version = _VERSION
if version == "Lua 5.2" then _ENV = nil end
local any = m.P(1)
-- Pre-defined names
local Predef = { nl = m.P"\n" }
local mem
local fmem
local gmem
local function updatelocale ()
mm.locale(Predef)
Predef.a = Predef.alpha
Predef.c = Predef.cntrl
Predef.d = Predef.digit
Predef.g = Predef.graph
Predef.l = Predef.lower
Predef.p = Predef.punct
Predef.s = Predef.space
Predef.u = Predef.upper
Predef.w = Predef.alnum
Predef.x = Predef.xdigit
Predef.A = any - Predef.a
Predef.C = any - Predef.c
Predef.D = any - Predef.d
Predef.G = any - Predef.g
Predef.L = any - Predef.l
Predef.P = any - Predef.p
Predef.S = any - Predef.s
Predef.U = any - Predef.u
Predef.W = any - Predef.w
Predef.X = any - Predef.x
mem = {} -- restart memoization
fmem = {}
gmem = {}
local mt = {__mode = "v"}
setmetatable(mem, mt)
setmetatable(fmem, mt)
setmetatable(gmem, mt)
end
updatelocale()
local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end)
local function getdef (id, Defs)
local c = Defs and Defs[id]
if not c then error("undefined name: " .. id) end
return c
end
local function patt_error (s, i)
local msg = (#s < i + 20) and s:sub(i)
or s:sub(i,i+20) .. "..."
msg = ("pattern error near '%s'"):format(msg)
error(msg, 2)
end
local function mult (p, n)
local np = mm.P(true)
while n >= 1 do
if n%2 >= 1 then np = np * p end
p = p * p
n = n/2
end
return np
end
local function equalcap (s, i, c)
if type(c) ~= "string" then return nil end
local e = #c + i
if s:sub(i, e - 1) == c then return e else return nil end
end
local S = (m.S(" \f\n\r\t\v") + "--" * (any - Predef.nl)^0)^0
local name = m.R("AZ", "az") * m.R("AZ", "az", "__", "09")^0
local arrow = S * "<-"
local exp_follow = m.P"/" + ")" + "}" + ":}" + "~}" + (name * arrow) + -1
name = m.C(name)
-- identifiers only have meaning in a given environment
local Identifier = name * m.Carg(1)
local num = m.C(m.R"09"^1) * S / tonumber
local String = "'" * m.C((any - "'")^0) * "'" +
'"' * m.C((any - '"')^0) * '"'
local defined = "%" * Identifier / function (c,Defs)
local cat = Defs and Defs[c] or Predef[c]
if not cat then error ("name '" .. c .. "' undefined") end
return cat
end
local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R
local item = defined + Range + m.C(any)
local Class =
"["
* (m.C(m.P"^"^-1)) -- optional complement symbol
* m.Cf(item * (item - "]")^0, mt.__add) /
function (c, p) return c == "^" and any - p or p end
* "]"
local function adddef (t, k, Defs, exp)
if t[k] then
error("'"..k.."' already defined as a rule")
else
t[k] = exp
end
return t
end
local function firstdef (n, Defs, r) return adddef({n}, n, Defs, r) end
local exp = m.P{ "Exp",
Exp = S * ( m.V"Grammar"
+ m.Cf(m.V"Seq" * ("/" * S * m.V"Seq")^0, mt.__add) );
Seq = m.Cf(m.Cc(m.P"") * m.V"Prefix"^0 , mt.__mul)
* (#exp_follow + patt_error);
Prefix = "&" * S * m.V"Prefix" / mt.__len
+ "!" * S * m.V"Prefix" / mt.__unm
+ m.V"Suffix";
Suffix = m.Cf(m.V"Primary" * S *
( ( m.P"+" * m.Cc(1, mt.__pow)
+ m.P"*" * m.Cc(0, mt.__pow)
+ m.P"?" * m.Cc(-1, mt.__pow)
+ "^" * ( m.Cg(num * m.Cc(mult))
+ m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow))
)
+ "->" * S * ( m.Cg(String * m.Cc(mt.__div))
+ m.P"{}" * m.Cc(nil, m.Ct)
+ m.Cg(Identifier / getdef * m.Cc(mt.__div))
)
+ "=>" * S * m.Cg(Identifier / getdef * m.Cc(m.Cmt))
) * S
)^0, function (a,b,f) return f(a,b) end );
Primary = "(" * m.V"Exp" * ")"
+ String / mm.P
+ Class
+ defined
+ "{:" * (name * ":" + m.Cc(nil)) * m.V"Exp" * ":}" /
function (n, p) return mm.Cg(p, n) end
+ "=" * name / function (n) return mm.Cmt(mm.Cb(n), equalcap) end
+ m.P"{}" / mm.Cp
+ "{~" * m.V"Exp" * "~}" / mm.Cs
+ "{" * m.V"Exp" * "}" / mm.C
+ m.P"." * m.Cc(any)
+ name * -arrow / mm.V
+ "<" * name * ">" / mm.V;
Definition = Identifier * arrow * m.V"Exp";
Grammar = m.Cf(m.V"Definition" / firstdef * m.Cg(m.V"Definition")^0, adddef) /
mm.P
}
local pattern = S * exp / mm.P * (-any + patt_error)
local function compile (p, defs)
if mm.type(p) == "pattern" then return p end -- already compiled
local cp = pattern:match(p, 1, defs)
if not cp then error("incorrect pattern", 3) end
return cp
end
local function match (s, p, i)
local cp = mem[p]
if not cp then
cp = compile(p)
mem[p] = cp
end
return cp:match(s, i or 1)
end
local function find (s, p, i)
local cp = fmem[p]
if not cp then
cp = compile(p)
cp = mm.P{ mm.Cp() * cp + 1 * mm.V(1) }
fmem[p] = cp
end
return cp:match(s, i or 1)
end
local function gsub (s, p, rep)
local g = gmem[p] or {} -- ensure gmem[p] is not collected while here
gmem[p] = g
local cp = g[rep]
if not cp then
cp = compile(p)
cp = mm.Cs((cp / rep + 1)^0)
g[rep] = cp
end
return cp:match(s)
end
-- exported names
local re = {
compile = compile,
match = match,
find = find,
gsub = gsub,
updatelocale = updatelocale,
}
if version == "Lua 5.1" then _G.re = re end
return re

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +0,0 @@
.PHONY : all clean
all : protobuf.so addressbook.pb
LIBSRCS = context.c varint.c array.c pattern.c register.c proto.c map.c alloc.c rmessage.c wmessage.c bootstrap.c stringpool.c decode.c
protobuf.so : pbc-lua.c $(LIBSRCS)
gcc -O2 -Wall --shared -fPIC -o $@ $^
addressbook.pb : addressbook.proto
protoc -o$@ $<
clean :
rm protobuf.so addressbook.pb

View File

@@ -1,2 +0,0 @@
See https://github.com/cloudwu/pbc

View File

@@ -1,39 +0,0 @@
// See README.txt for information and build instructions.
package tutorial;
option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 id = 2; // Unique ID number for this person.
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;
repeated int32 test = 5 [packed=true];
extensions 10 to max;
}
message Ext {
extend Person {
optional int32 test = 10;
}
}
// Our address book file is just one of these.
message AddressBook {
repeated Person person = 1;
}

View File

@@ -1,84 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
static int _g = 0;
void * _pbcM_malloc(size_t sz) {
++ _g;
return malloc(sz);
}
void _pbcM_free(void *p) {
if (p) {
-- _g;
free(p);
}
}
void* _pbcM_realloc(void *p, size_t sz) {
return realloc(p,sz);
}
void _pbcM_memory() {
printf("%d\n",_g);
}
struct heap_page {
struct heap_page * next;
};
struct heap {
struct heap_page *current;
int size;
int used;
};
struct heap *
_pbcH_new(int pagesize) {
int cap = 1024;
while(cap < pagesize) {
cap *= 2;
}
struct heap * h = _pbcM_malloc(sizeof(struct heap));
h->current = _pbcM_malloc(sizeof(struct heap_page) + cap);
h->size = cap;
h->used = 0;
h->current->next = NULL;
return h;
}
void
_pbcH_delete(struct heap *h) {
struct heap_page * p = h->current;
struct heap_page * next = p->next;
for(;;) {
_pbcM_free(p);
if (next == NULL)
break;
p = next;
next = p->next;
}
_pbcM_free(h);
}
void*
_pbcH_alloc(struct heap *h, int size) {
size = (size + 3) & ~3;
if (h->size - h->used < size) {
struct heap_page * p;
if (size < h->size) {
p = _pbcM_malloc(sizeof(struct heap_page) + h->size);
} else {
p = _pbcM_malloc(sizeof(struct heap_page) + size);
}
p->next = h->current;
h->current = p;
h->used = size;
return (p+1);
} else {
char * buffer = (char *)(h->current + 1);
buffer += h->used;
h->used += size;
return buffer;
}
}

View File

@@ -1,25 +0,0 @@
#ifndef PROTOBUF_C_ALLOC_H
#define PROTOBUF_C_ALLOC_H
#include <stdlib.h>
#include <string.h>
void * _pbcM_malloc(size_t sz);
void _pbcM_free(void *p);
void * _pbcM_realloc(void *p, size_t sz);
void _pbcM_memory();
struct heap;
struct heap * _pbcH_new(int pagesize);
void _pbcH_delete(struct heap *);
void* _pbcH_alloc(struct heap *, int size);
#define HMALLOC(size) ((h) ? _pbcH_alloc(h, size) : _pbcM_malloc(size))
#define malloc _pbcM_malloc
#define free _pbcM_free
#define realloc _pbcM_realloc
#define memory _pbcM_memory
#endif

View File

@@ -1,139 +0,0 @@
#include "pbc.h"
#include "array.h"
#include "alloc.h"
#include <stdlib.h>
#include <string.h>
struct array {
int number;
struct heap *heap;
union _pbc_var * a;
};
#define INNER_FIELD ((PBC_ARRAY_CAP - sizeof(struct array)) / sizeof(pbc_var))
void
_pbcA_open(pbc_array _array) {
struct array * a = (struct array *)_array;
a->number = 0;
a->heap = NULL;
a->a = (union _pbc_var *)(a+1);
}
void
_pbcA_open_heap(pbc_array _array, struct heap *h) {
struct array * a = (struct array *)_array;
a->number = 0;
a->heap = h;
a->a = (union _pbc_var *)(a+1);
}
void
_pbcA_close(pbc_array _array) {
struct array * a = (struct array *)_array;
if (a->heap == NULL && a->a != NULL && (union _pbc_var *)(a+1) != a->a) {
_pbcM_free(a->a);
a->a = NULL;
}
}
void
_pbcA_push(pbc_array _array, pbc_var var) {
struct array * a = (struct array *)_array;
if (a->number == 0) {
a->a = (union _pbc_var *)(a+1);
} else if (a->number >= INNER_FIELD) {
if (a->number == INNER_FIELD) {
int cap = 1;
while (cap <= a->number + 1)
cap *= 2;
struct heap * h = a->heap;
union _pbc_var * outer = HMALLOC(cap * sizeof(union _pbc_var));
memcpy(outer , a->a , INNER_FIELD * sizeof(pbc_var));
a->a = outer;
} else {
int size=a->number;
if (((size + 1) ^ size) > size) {
struct heap * h = a->heap;
if (h) {
void * old = a->a;
a->a = _pbcH_alloc(h, sizeof(union _pbc_var) * (size+1) * 2);
memcpy(a->a, old, sizeof(union _pbc_var) * size);
} else {
a->a=_pbcM_realloc(a->a,sizeof(union _pbc_var) * (size+1) * 2);
}
}
}
}
a->a[a->number] = *var;
++ a->number;
}
void
_pbcA_index(pbc_array _array, int idx, pbc_var var)
{
struct array * a = (struct array *)_array;
var[0] = a->a[idx];
}
void *
_pbcA_index_p(pbc_array _array, int idx)
{
struct array * a = (struct array *)_array;
return &(a->a[idx]);
}
int
pbc_array_size(pbc_array _array) {
struct array * a = (struct array *)_array;
return a->number;
}
uint32_t
pbc_array_integer(pbc_array array, int index, uint32_t *hi) {
pbc_var var;
_pbcA_index(array , index , var);
if (hi) {
*hi = var->integer.hi;
}
return var->integer.low;
}
double
pbc_array_real(pbc_array array, int index) {
pbc_var var;
_pbcA_index(array , index , var);
return var->real;
}
struct pbc_slice *
pbc_array_slice(pbc_array _array, int index) {
struct array * a = (struct array *)_array;
if (index <0 || index > a->number) {
return NULL;
}
return (struct pbc_slice *) &(a->a[index]);
}
void
pbc_array_push_integer(pbc_array array, uint32_t low, uint32_t hi) {
pbc_var var;
var->integer.low = low;
var->integer.hi = hi;
_pbcA_push(array,var);
}
void
pbc_array_push_slice(pbc_array array, struct pbc_slice *s) {
pbc_var var;
var->m = *s;
_pbcA_push(array,var);
}
void
pbc_array_push_real(pbc_array array, double v) {
pbc_var var;
var->real = v;
_pbcA_push(array,var);
}

View File

@@ -1,31 +0,0 @@
#ifndef PROTOBUF_C_ARRAY_H
#define PROTOBUF_C_ARRAY_H
#include "varint.h"
#include "pbc.h"
#include "alloc.h"
typedef union _pbc_var {
struct longlong integer;
double real;
struct {
const char * str;
int len;
} s;
struct {
int id;
const char * name;
} e;
struct pbc_slice m;
void * p[2];
} pbc_var[1];
void _pbcA_open(pbc_array);
void _pbcA_open_heap(pbc_array, struct heap *h);
void _pbcA_close(pbc_array);
void _pbcA_push(pbc_array, pbc_var var);
void _pbcA_index(pbc_array , int idx, pbc_var var);
void * _pbcA_index_p(pbc_array _array, int idx);
#endif

View File

@@ -1,303 +0,0 @@
#include "pbc.h"
#include "map.h"
#include "context.h"
#include "pattern.h"
#include "proto.h"
#include "alloc.h"
#include "bootstrap.h"
#include "stringpool.h"
#include "array.h"
#include "descriptor.pbc.h"
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdint.h>
/*
// Descriptor
// google.protobuf.Descriptor.proto encoded in descriptor.pbc.h with proto pbc.file .
package pbc;
message field {
optional string name = 1;
optional int32 id = 2;
optional int32 label = 3; // 0 optional 1 required 2 repeated
optional int32 type = 4; // type_id
optional string type_name = 5;
optional int32 default_int = 6;
optional string default_string = 7;
optional double default_real = 8;
}
message file {
optional string name = 1;
repeated string dependency = 2;
repeated string message_name = 3;
repeated int32 message_size = 4;
repeated field message_field = 5;
repeated string enum_name = 6;
repeated int32 enum_size = 7;
repeated string enum_string = 8;
repeated int32 enum_id = 9;
}
*/
struct field_t {
struct pbc_slice name;
int32_t id;
int32_t label;
int32_t type;
struct pbc_slice type_name;
int32_t default_integer;
struct pbc_slice default_string;
double default_real;
};
struct file_t {
struct pbc_slice name; // string
pbc_array dependency; // string
pbc_array message_name; // string
pbc_array message_size; // int32
pbc_array message_field; // field_t
pbc_array enum_name; // string
pbc_array enum_size; // int32
pbc_array enum_string; // string
pbc_array enum_id; // int32
};
static void
set_enum_one(struct pbc_env *p, struct file_t *file, const char *name, int start, int sz) {
struct map_kv *table = malloc(sz * sizeof(struct map_kv));
int i;
for (i=0;i<sz;i++) {
pbc_var id;
pbc_var string;
_pbcA_index(file->enum_id, start+i, id);
_pbcA_index(file->enum_string, start+i, string);
table[i].id = (int)id->integer.low;
table[i].pointer = (void *)string->s.str;
}
_pbcP_push_enum(p,name,table,sz);
free(table);
}
static void
set_enums(struct pbc_env *p, struct file_t *file) {
int n = pbc_array_size(file->enum_size);
int i;
int start = 0;
for (i=0;i<n;i++) {
pbc_var name;
_pbcA_index(file->enum_name,i,name);
pbc_var var;
_pbcA_index(file->enum_size,i,var);
set_enum_one(p, file, name->s.str, start , (int)var->integer.low);
start += var->integer.low;
}
}
static void
set_default(struct _field *f, struct field_t *input) {
switch (f->type) {
case PTYPE_DOUBLE:
case PTYPE_FLOAT:
f->default_v->real = input->default_real;
break;
case PTYPE_STRING:
case PTYPE_ENUM:
f->default_v->m = input->default_string;
break;
default:
f->default_v->integer.low = input->default_integer;
break;
}
}
static void
set_msg_one(struct pbc_pattern * FIELD_T, struct pbc_env *p, struct file_t *file, const char *name, int start, int sz , pbc_array queue) {
int i;
for (i=0;i<sz;i++) {
pbc_var _field;
_pbcA_index(file->message_field, start+i, _field);
struct field_t field;
int ret = pbc_pattern_unpack(FIELD_T, &_field->m, &field);
if (ret != 0) {
continue;
}
struct _field f;
f.id = field.id;
f.name = field.name.buffer;
f.type = field.type;
f.label = field.label;
f.type_name.n = field.type_name.buffer;
set_default(&f, &field);
_pbcP_push_message(p,name, &f , queue);
// don't need to close pattern since no array
}
_pbcP_init_message(p, name);
}
static void
set_msgs(struct pbc_pattern * FIELD_T, struct pbc_env *p, struct file_t *file , pbc_array queue) {
int n = pbc_array_size(file->message_size);
int i;
int start = 0;
for (i=0;i<n;i++) {
pbc_var name;
_pbcA_index(file->message_name,i,name);
pbc_var sz;
_pbcA_index(file->message_size,i,sz);
set_msg_one(FIELD_T, p, file, name->s.str, start , (int)sz->integer.low , queue);
start += sz->integer.low;
}
}
static void
set_field_one(struct pbc_env *p, struct _field *f) {
const char * type_name = f->type_name.n;
if (f->type == PTYPE_MESSAGE) {
f->type_name.m = _pbcM_sp_query(p->msgs, type_name);
// printf("MESSAGE: %s %p\n",type_name, f->type_name.m);
} else if (f->type == PTYPE_ENUM) {
f->type_name.e = _pbcM_sp_query(p->enums, type_name);
// printf("ENUM: %s %p ",type_name, f->type_name.e);
const char * str = f->default_v->s.str;
if (str && str[0]) {
int err = _pbcM_si_query(f->type_name.e->name, str , &(f->default_v->e.id));
if (err < 0)
goto _default;
f->default_v->e.name = _pbcM_ip_query(f->type_name.e->id, f->default_v->e.id);
// printf("[%s %d]\n",str,f->default_v->e.id);
} else {
_default:
memcpy(f->default_v, f->type_name.e->default_v, sizeof(pbc_var));
// printf("(%s %d)\n",f->default_v->e.name,f->default_v->e.id);
}
}
}
void
_pbcB_register_fields(struct pbc_env *p, pbc_array queue) {
int sz = pbc_array_size(queue);
int i;
for (i=0;i<sz;i++) {
pbc_var atom;
_pbcA_index(queue,i,atom);
struct _field * f = atom->m.buffer;
set_field_one(p, f);
}
}
static void
_set_string(struct _pattern_field * f) {
f->ptype = PTYPE_STRING;
f->ctype = CTYPE_VAR;
f->defv->s.str = "";
f->defv->s.len = 0;
}
static void
_set_int32(struct _pattern_field * f) {
f->ptype = PTYPE_INT32;
f->ctype = CTYPE_INT32;
}
static void
_set_double(struct _pattern_field * f) {
f->ptype = PTYPE_DOUBLE;
f->ctype = CTYPE_DOUBLE;
}
static void
_set_message_array(struct _pattern_field *f) {
f->ptype = PTYPE_MESSAGE;
f->ctype = CTYPE_ARRAY;
}
static void
_set_string_array(struct _pattern_field * f) {
f->ptype = PTYPE_STRING;
f->ctype = CTYPE_ARRAY;
}
static void
_set_int32_array(struct _pattern_field * f) {
f->ptype = PTYPE_INT32;
f->ctype = CTYPE_ARRAY;
}
#define SET_PATTERN(pat , idx , pat_type, field_name , type) \
pat->f[idx].id = idx+1 ; \
pat->f[idx].offset = offsetof(struct pat_type, field_name); \
_set_##type(&pat->f[idx]);
#define F(idx,field_name,type) SET_PATTERN(FIELD_T, idx, field_t ,field_name, type)
#define D(idx,field_name,type) SET_PATTERN(FILE_T, idx, file_t ,field_name, type)
static int
register_internal(struct pbc_env * p, struct pbc_slice *slice) {
struct pbc_pattern * FIELD_T = _pbcP_new(p,8);
F(0,name,string);
F(1,id,int32);
F(2,label,int32);
F(3,type,int32);
F(4,type_name,string);
F(5,default_integer,int32);
F(6,default_string,string);
F(7,default_real,double);
struct pbc_pattern * FILE_T = _pbcP_new(p,10);
D(0,name,string);
D(1,dependency,string_array);
D(2,message_name,string_array);
D(3,message_size,int32_array);
D(4,message_field,message_array);
D(5,enum_name,string_array);
D(6,enum_size,int32_array);
D(7,enum_string,string_array);
D(8,enum_id,int32_array);
int ret = 0;
struct file_t file;
int r = pbc_pattern_unpack(FILE_T, slice, &file);
if (r != 0) {
ret = 1;
goto _return;
}
_pbcM_sp_insert(p->files , file.name.buffer, NULL);
pbc_array queue;
_pbcA_open(queue);
set_enums(p, &file);
set_msgs(FIELD_T, p, &file, queue);
_pbcB_register_fields(p, queue);
_pbcA_close(queue);
pbc_pattern_close_arrays(FILE_T, &file);
_return:
free(FIELD_T);
free(FILE_T);
return ret;
}
void
_pbcB_init(struct pbc_env * p) {
struct pbc_slice slice = { pbc_descriptor,sizeof(pbc_descriptor) };
register_internal(p,&slice);
}

View File

@@ -1,10 +0,0 @@
#ifndef PROTOBUF_C_BOOTSTRAP_H
#define PROTOBUF_C_BOOTSTRAP_H
#include "proto.h"
#include "pbc.h"
void _pbcB_init(struct pbc_env *);
void _pbcB_register_fields(struct pbc_env *, pbc_array queue);
#endif

View File

@@ -1,278 +0,0 @@
#include "pbc.h"
#include "alloc.h"
#include "varint.h"
#include "context.h"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#define INNER_ATOM ((PBC_CONTEXT_CAP - sizeof(struct context)) / sizeof(struct atom))
static char *
wiretype_decode(uint8_t *buffer, int cap , struct atom *a , int start)
{
uint8_t temp[10];
struct longlong r;
int len;
if (cap >= 10) {
len = _pbcV_decode(buffer, &r);
if (r.hi !=0)
return NULL;
} else {
memcpy(temp, buffer , cap);
len = _pbcV_decode(temp, &r);
if (len > cap || r.hi !=0)
return NULL;
}
int wiretype = r.low & 7;
a->wire_id = r.low;
buffer += len;
start += len;
cap -=len;
switch (wiretype) {
case WT_VARINT :
if (cap >=10) {
len = _pbcV_decode(buffer, &a->v.i);
} else {
memcpy(temp, buffer , cap);
len = _pbcV_decode(temp, &a->v.i);
if (cap < len)
return NULL;
}
return (char *)buffer+len;
case WT_BIT64 :
if (cap < 8)
return NULL;
a->v.i.low = buffer[0] |
buffer[1] << 8 |
buffer[2] << 16 |
buffer[3] << 24;
a->v.i.hi = buffer[4] |
buffer[5] << 8 |
buffer[6] << 16 |
buffer[7] << 24;
return (char *)buffer + 8;
case WT_LEND :
if (cap >=10) {
len = _pbcV_decode(buffer, &r);
} else {
memcpy(temp, buffer , cap);
len = _pbcV_decode(temp, &r);
}
if (cap < len + r.low || r.hi !=0)
return NULL;
a->v.s.start = start + len;
a->v.s.end = start + len + r.low;
return (char *)buffer + len + r.low;
case WT_BIT32 :
if (cap < 4)
return NULL;
a->v.i.low = buffer[0] |
buffer[1] << 8 |
buffer[2] << 16 |
buffer[3] << 24;
a->v.i.hi = 0;
return (char *)buffer + 4;
default:
return NULL;
}
}
static inline int
_decode_varint(uint8_t * buffer, int size , struct atom * a) {
a->wire_id = WT_VARINT;
if (size < 10) {
uint8_t temp[10];
memcpy(temp,buffer,size);
return _pbcV_decode(temp , &(a->v.i));
} else {
return _pbcV_decode(buffer , &(a->v.i));
}
}
static int
_open_packed_varint(struct context * ctx , uint8_t * buffer, int size) {
struct atom * a = (struct atom *)(ctx + 1);
int i;
for (i=0;i<INNER_ATOM;i++) {
if (size == 0)
break;
int len = _decode_varint(buffer, size, &a[i]);
buffer += len;
size -= len;
}
if (size == 0) {
ctx->a = a;
} else {
int cap = 64;
ctx->a = malloc(cap * sizeof(struct atom));
while (size > 0) {
if (i >= cap) {
cap = cap + 64;
ctx->a = realloc(ctx->a, cap * sizeof(struct atom));
continue;
}
int len = _decode_varint(buffer, size, &a[i]);
buffer += len;
size -= len;
++i;
}
memcpy(ctx->a, a , sizeof(struct atom) * INNER_ATOM);
}
ctx->number = i;
return i;
}
int
_pbcC_open_packed(pbc_ctx _ctx, int ptype, void *buffer, int size) {
struct context * ctx = (struct context *)_ctx;
ctx->buffer = buffer;
ctx->size = size;
ctx->number = 0;
ctx->a = NULL;
if (buffer == NULL || size == 0) {
return 0;
}
int bits = 0;
switch (ptype) {
case PTYPE_INT64:
case PTYPE_UINT64:
case PTYPE_INT32:
case PTYPE_BOOL:
case PTYPE_UINT32:
case PTYPE_ENUM:
case PTYPE_SINT32:
case PTYPE_SINT64:
return _open_packed_varint(ctx , buffer, size);
case PTYPE_DOUBLE:
case PTYPE_FIXED64:
case PTYPE_SFIXED64:
ctx->number = size / 8;
bits = 64;
break;
case PTYPE_FLOAT:
case PTYPE_FIXED32:
case PTYPE_SFIXED32:
ctx->number = size / 4;
bits = 32;
break;
default:
return 0;
}
struct atom * a = (struct atom *)(ctx + 1);
if (ctx->number > INNER_ATOM) {
ctx->a = malloc(ctx->number * sizeof(struct atom));
a = ctx->a;
} else {
ctx->a = a;
}
int i;
if (bits == 64) {
uint8_t * data = buffer;
for (i=0;i<ctx->number;i++) {
a[i].wire_id = WT_BIT64;
a[i].v.i.low = data[0] |
data[1] << 8 |
data[2] << 16 |
data[3] << 24;
a[i].v.i.hi = data[4] |
data[5] << 8 |
data[6] << 16 |
data[7] << 24;
data += 8;
}
} else {
uint8_t * data = buffer;
for (i=0;i<ctx->number;i++) {
a[i].wire_id = WT_BIT32;
a[i].v.i.low = data[0] |
data[1] << 8 |
data[2] << 16 |
data[3] << 24;
a[i].v.i.hi = 0;
data += 4;
}
}
return ctx->number;
}
int
_pbcC_open(pbc_ctx _ctx , void *buffer, int size) {
struct context * ctx = (struct context *)_ctx;
ctx->buffer = buffer;
ctx->size = size;
if (buffer == NULL || size == 0) {
ctx->number = 0;
ctx->a = NULL;
return 0;
}
struct atom * a = (struct atom *)(ctx + 1);
int i;
int start = 0;
ctx->a = a;
for (i=0;i<INNER_ATOM;i++) {
if (size == 0)
break;
char * next = wiretype_decode(buffer, size , &a[i] , start);
if (next == NULL)
return -i;
start += next - (char *)buffer;
size -= next - (char *)buffer;
buffer = next;
}
if (size > 0) {
int cap = 64;
ctx->a = malloc(cap * sizeof(struct atom));
while (size > 0) {
if (i >= cap) {
cap = cap + 64;
ctx->a = realloc(ctx->a, cap * sizeof(struct atom));
continue;
}
char * next = wiretype_decode(buffer, size , &ctx->a[i] , start);
if (next == NULL) {
return -i;
}
start += next - (char *)buffer;
size -= next - (char *)buffer;
buffer = next;
++i;
}
memcpy(ctx->a, a , sizeof(struct atom) * INNER_ATOM);
}
ctx->number = i;
return i;
}
void
_pbcC_close(pbc_ctx _ctx) {
struct context * ctx = (struct context *)_ctx;
if (ctx->a != NULL && (struct atom *)(ctx+1) != ctx->a) {
free(ctx->a);
ctx->a = NULL;
}
}

View File

@@ -1,140 +0,0 @@
#ifndef PROTOBUF_C_CONTEXT_H
#define PROTOBUF_C_CONTEXT_H
#include <stdint.h>
#include "array.h"
#define PBC_CONTEXT_CAP 256
// wiretype
#define WT_VARINT 0
#define WT_BIT64 1
#define WT_LEND 2
#define WT_BIT32 5
#define CTYPE_INT32 1
#define CTYPE_INT64 2
#define CTYPE_DOUBLE 3
#define CTYPE_FLOAT 4
#define CTYPE_POINTER 5
#define CTYPE_BOOL 6
#define CTYPE_INT8 7
#define CTYPE_INT16 8
#define CTYPE_ARRAY 9
#define CTYPE_VAR 10
#define CTYPE_PACKED 11
#define PTYPE_DOUBLE 1
#define PTYPE_FLOAT 2
#define PTYPE_INT64 3 // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if negative values are likely.
#define PTYPE_UINT64 4
#define PTYPE_INT32 5 // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if negative values are likely.
#define PTYPE_FIXED64 6
#define PTYPE_FIXED32 7
#define PTYPE_BOOL 8
#define PTYPE_STRING 9
#define PTYPE_GROUP 10 // Tag-delimited aggregate.
#define PTYPE_MESSAGE 11 // Length-delimited aggregate.
#define PTYPE_BYTES 12
#define PTYPE_UINT32 13
#define PTYPE_ENUM 14
#define PTYPE_SFIXED32 15
#define PTYPE_SFIXED64 16
#define PTYPE_SINT32 17 // Uses ZigZag encoding.
#define PTYPE_SINT64 18 // Uses ZigZag encoding.
struct slice {
int start;
int end;
};
struct atom {
int wire_id;
union {
struct slice s;
struct longlong i;
} v;
};
struct context {
char * buffer;
int size;
int number;
struct atom * a;
};
typedef struct _pbc_ctx { char _data[PBC_CONTEXT_CAP]; } pbc_ctx[1];
int _pbcC_open(pbc_ctx , void *buffer, int size); // <=0 failed
int _pbcC_open_packed(pbc_ctx _ctx, int ptype, void *buffer, int size);
void _pbcC_close(pbc_ctx);
static inline double
read_double(struct atom * a) {
union {
uint64_t i;
double d;
} u;
u.i = (uint64_t) a->v.i.low | (uint64_t) a->v.i.hi << 32;
return u.d;
}
static inline float
read_float(struct atom * a) {
union {
uint32_t i;
float f;
} u;
u.i = a->v.i.low;
return u.f;
}
static inline void
double_encode(double v , uint8_t * buffer) {
union {
double v;
uint64_t e;
} u;
u.v = v;
buffer[0] = (uint8_t) (u.e & 0xff);
buffer[1] = (uint8_t) (u.e >> 8 & 0xff);
buffer[2] = (uint8_t) (u.e >> 16 & 0xff);
buffer[3] = (uint8_t) (u.e >> 24 & 0xff);
buffer[4] = (uint8_t) (u.e >> 32 & 0xff);
buffer[5] = (uint8_t) (u.e >> 40 & 0xff);
buffer[6] = (uint8_t) (u.e >> 48 & 0xff);
buffer[7] = (uint8_t) (u.e >> 56 & 0xff);
}
static inline void
float_encode(float v , uint8_t * buffer) {
union {
float v;
uint32_t e;
} u;
u.v = v;
buffer[0] = (uint8_t) (u.e & 0xff);
buffer[1] = (uint8_t) (u.e >> 8 & 0xff);
buffer[2] = (uint8_t) (u.e >> 16 & 0xff);
buffer[3] = (uint8_t) (u.e >> 24 & 0xff);
}
#define CHECK_LEND(a,err) if ((a->wire_id & 7) != WT_LEND) return err;
#if 0
/* maybe we don't need check these wire type */
#define CHECK_VARINT(a,err) if ((a->wire_id & 7) != WT_VARINT) return err;
#define CHECK_BIT32(a,err) if ((a->wire_id & 7) != WT_BIT32) return err;
#define CHECK_BIT64(a,err) if ((a->wire_id & 7) != WT_BIT64) return err;
#else
#define CHECK_VARINT(a,err)
#define CHECK_BIT32(a,err)
#define CHECK_BIT64(a,err)
#endif
#endif

View File

@@ -1,349 +0,0 @@
#include "pbc.h"
#include "alloc.h"
#include "context.h"
#include "proto.h"
#include "varint.h"
#include <assert.h>
static const char * TYPENAME[] = {
"invalid", // 0
"integer", // 1
"real", // 2
"boolean", // 3
"enum", // 4
"string", // 5
"message", // 6
"fixed64", // 7
"fixed32", // 8
"bytes", // 9
"int64", // 10
"uint", // 11
};
static int
call_unknown(pbc_decoder f, void * ud, int id, struct atom *a, uint8_t * start) {
union pbc_value v;
switch (a->wire_id) {
case WT_VARINT:
v.i.low = a->v.i.low;
v.i.hi = a->v.i.hi;
f(ud, PBC_INT, TYPENAME[PBC_INT], &v, id , NULL);
break;
case WT_BIT64:
v.i.low = a->v.i.low;
v.i.hi = a->v.i.hi;
f(ud, PBC_FIXED64, TYPENAME[PBC_FIXED64], &v, id , NULL);
break;
case WT_LEND:
v.s.buffer = (char*)start + a->v.s.start;
v.s.len = a->v.s.end - a->v.s.start;
f(ud, PBC_BYTES, TYPENAME[PBC_BYTES], &v, id , NULL);
break;
case WT_BIT32:
v.i.low = a->v.i.low;
v.i.hi = 0;
f(ud, PBC_FIXED32, TYPENAME[PBC_FIXED32], &v, id , NULL);
break;
default:
return 1;
}
return 0;
}
static int
call_type(pbc_decoder pd, void * ud, struct _field *f, struct atom *a, uint8_t * start) {
union pbc_value v;
const char * typename = NULL;
int type = _pbcP_type(f, &typename);
assert(type != 0);
if (typename == NULL) {
typename = TYPENAME[type & ~PBC_REPEATED];
}
switch (f->type) {
case PTYPE_DOUBLE:
CHECK_BIT64(a, -1);
v.f = read_double(a);
break;
case PTYPE_FLOAT:
CHECK_BIT32(a, -1);
v.f = (double) read_float(a);
break;
case PTYPE_ENUM:
CHECK_VARINT(a, -1);
v.e.id = a->v.i.low;
v.e.name = _pbcM_ip_query(f->type_name.e->id , v.e.id);
break;
case PTYPE_INT64:
case PTYPE_UINT64:
CHECK_VARINT(a, -1);
v.i.low = a->v.i.low;
v.i.hi = a->v.i.hi;
break;
case PTYPE_FIXED64:
case PTYPE_SFIXED64:
CHECK_BIT64(a, -1);
v.i.low = a->v.i.low;
v.i.hi = a->v.i.hi;
break;
case PTYPE_INT32:
case PTYPE_UINT32:
case PTYPE_BOOL:
CHECK_VARINT(a, -1);
v.i.low = a->v.i.low;
v.i.hi = 0;
break;
case PTYPE_FIXED32:
case PTYPE_SFIXED32:
CHECK_BIT32(a, -1);
v.i.low = a->v.i.low;
v.i.hi = 0;
break;
case PTYPE_SINT32:
CHECK_VARINT(a, -1);
v.i.low = a->v.i.low;
v.i.hi = a->v.i.hi;
_pbcV_dezigzag32((struct longlong *)&(v.i));
break;
case PTYPE_SINT64:
CHECK_VARINT(a, -1);
v.i.low = a->v.i.low;
v.i.hi = a->v.i.hi;
_pbcV_dezigzag64((struct longlong *)&(v.i));
break;
case PTYPE_STRING:
case PTYPE_BYTES:
case PTYPE_MESSAGE:
CHECK_LEND(a, -1);
v.s.buffer = start + a->v.s.start;
v.s.len = a->v.s.end - a->v.s.start;
break;
default:
assert(0);
break;
}
pd(ud, type, typename, &v, f->id, f->name);
return 0;
}
static int
call_array(pbc_decoder pd, void * ud, struct _field *f, uint8_t * buffer , int size) {
union pbc_value v;
const char * typename = NULL;
int type = _pbcP_type(f, &typename);
assert(type != 0);
if (typename == NULL) {
typename = TYPENAME[type & ~PBC_REPEATED];
}
v.i.hi = 0;
int i;
switch(f->type) {
case PTYPE_DOUBLE:
if (size % 8 != 0) {
return -1;
}
for (i=0;i<size;i+=8) {
union {
double d;
uint64_t i64;
} u;
u.i64 = (uint64_t)buffer[i] |
(uint64_t)buffer[i+1] << 8 |
(uint64_t)buffer[i+2] << 16 |
(uint64_t)buffer[i+3] << 24 |
(uint64_t)buffer[i+4] << 32 |
(uint64_t)buffer[i+5] << 40 |
(uint64_t)buffer[i+6] << 48 |
(uint64_t)buffer[i+7] << 56;
v.f = u.d;
pd(ud, type , typename, &v, f->id, f->name);
}
return size/8;
case PTYPE_FLOAT:
if (size % 4 != 0)
return -1;
for (i=0;i<size;i+=4) {
union {
float f;
uint32_t i32;
} u;
u.i32 = (uint32_t)buffer[i] |
(uint32_t)buffer[i+1] << 8 |
(uint32_t)buffer[i+2] << 16 |
(uint32_t)buffer[i+3] << 24;
v.f = (double)u.f;
pd(ud, type , typename, &v, f->id, f->name);
}
return size/4;
case PTYPE_FIXED32:
case PTYPE_SFIXED32:
if (size % 4 != 0)
return -1;
for (i=0;i<size;i+=4) {
v.i.low = (uint32_t)buffer[i] |
(uint32_t)buffer[i+1] << 8 |
(uint32_t)buffer[i+2] << 16 |
(uint32_t)buffer[i+3] << 24;
pd(ud, type , typename, &v, f->id, f->name);
}
return size/4;
case PTYPE_FIXED64:
case PTYPE_SFIXED64:
if (size % 8 != 0)
return -1;
for (i=0;i<size;i+=8) {
v.i.low = (uint32_t)buffer[i] |
(uint32_t)buffer[i+1] << 8 |
(uint32_t)buffer[i+2] << 16 |
(uint32_t)buffer[i+3] << 24;
v.i.hi = (uint32_t)buffer[i+4] |
(uint32_t)buffer[i+5] << 8 |
(uint32_t)buffer[i+6] << 16 |
(uint32_t)buffer[i+7] << 24;
pd(ud, type , typename, &v, f->id, f->name);
}
return size/8;
case PTYPE_INT64:
case PTYPE_UINT64:
case PTYPE_INT32:
case PTYPE_UINT32:
case PTYPE_BOOL: {
int n = 0;
while (size > 0) {
int len;
if (size >= 10) {
len = _pbcV_decode(buffer, (struct longlong *)&(v.i));
} else {
uint8_t temp[10];
memcpy(temp, buffer, size);
len = _pbcV_decode(buffer, (struct longlong *)&(v.i));
if (len > size)
return -1;
}
pd(ud, type , typename, &v, f->id, f->name);
buffer += len;
size -= len;
++n;
}
return n;
}
case PTYPE_ENUM: {
int n = 0;
while (size > 0) {
int len;
if (size >= 10) {
len = _pbcV_decode(buffer, (struct longlong *)&(v.i));
} else {
uint8_t temp[10];
memcpy(temp, buffer, size);
len = _pbcV_decode(buffer, (struct longlong *)&(v.i));
if (len > size)
return -1;
}
v.e.id = v.i.low;
v.e.name = _pbcM_ip_query(f->type_name.e->id , v.i.low);
pd(ud, type , typename, &v, f->id, f->name);
buffer += len;
size -= len;
++n;
}
return n;
}
case PTYPE_SINT32: {
int n = 0;
while (size > 0) {
int len;
if (size >= 10) {
len = _pbcV_decode(buffer, (struct longlong *)&(v.i));
_pbcV_dezigzag32((struct longlong *)&(v.i));
} else {
uint8_t temp[10];
memcpy(temp, buffer, size);
len = _pbcV_decode(buffer, (struct longlong *)&(v.i));
if (len > size)
return -1;
_pbcV_dezigzag32((struct longlong *)&(v.i));
}
pd(ud, type , typename, &v, f->id, f->name);
buffer += len;
size -= len;
++n;
}
return n;
}
case PTYPE_SINT64: {
int n = 0;
while (size > 0) {
int len;
if (size >= 10) {
len = _pbcV_decode(buffer, (struct longlong *)&(v.i));
_pbcV_dezigzag64((struct longlong *)&(v.i));
} else {
uint8_t temp[10];
memcpy(temp, buffer, size);
len = _pbcV_decode(buffer, (struct longlong *)&(v.i));
if (len > size)
return -1;
_pbcV_dezigzag64((struct longlong *)&(v.i));
}
pd(ud, type , typename, &v, f->id, f->name);
buffer += len;
size -= len;
++n;
}
return n;
}
default:
return -1;
}
}
int
pbc_decode(struct pbc_env * env, const char * typename , struct pbc_slice * slice, pbc_decoder pd, void *ud) {
struct _message * msg = _pbcP_get_message(env, typename);
if (msg == NULL) {
env->lasterror = "Proto not found";
return -1;
}
if (slice->len == 0) {
return 0;
}
pbc_ctx _ctx;
int count = _pbcC_open(_ctx,slice->buffer,slice->len);
if (count <= 0) {
env->lasterror = "decode context error";
_pbcC_close(_ctx);
return count - 1;
}
struct context * ctx = (struct context *)_ctx;
uint8_t * start = slice->buffer;
int i;
for (i=0;i<ctx->number;i++) {
int id = ctx->a[i].wire_id >> 3;
struct _field * f = _pbcM_ip_query(msg->id , id);
if (f==NULL) {
int err = call_unknown(pd,ud,id,&ctx->a[i],start);
if (err) {
_pbcC_close(_ctx);
return -i-1;
}
} else if (f->label == LABEL_PACKED) {
struct atom * a = &ctx->a[i];
int n = call_array(pd, ud, f , start + a->v.s.start , a->v.s.end - a->v.s.start);
if (n < 0) {
_pbcC_close(_ctx);
return -i-1;
}
} else {
if (call_type(pd,ud,f,&ctx->a[i],start) != 0) {
_pbcC_close(_ctx);
return -i-1;
}
}
}
_pbcC_close(_ctx);
return ctx->number;
}

View File

@@ -1,271 +0,0 @@
static unsigned char pbc_descriptor[] = {
72,1,72,2,72,3,72,4,72,5,72,6,72,7,72,8,
72,9,72,10,72,11,72,12,72,13,72,14,72,15,72,16,
72,17,72,18,72,1,72,2,72,3,72,1,72,2,72,3,
72,0,72,1,72,2,50,42,103,111,111,103,108,101,46,112,
114,111,116,111,98,117,102,46,70,105,101,108,100,68,101,115,
99,114,105,112,116,111,114,80,114,111,116,111,46,84,121,112,
101,0,50,43,103,111,111,103,108,101,46,112,114,111,116,111,
98,117,102,46,70,105,101,108,100,68,101,115,99,114,105,112,
116,111,114,80,114,111,116,111,46,76,97,98,101,108,0,50,
41,103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,
46,70,105,108,101,79,112,116,105,111,110,115,46,79,112,116,
105,109,105,122,101,77,111,100,101,0,50,35,103,111,111,103,
108,101,46,112,114,111,116,111,98,117,102,46,70,105,101,108,
100,79,112,116,105,111,110,115,46,67,84,121,112,101,0,66,
12,84,89,80,69,95,68,79,85,66,76,69,0,66,11,84,
89,80,69,95,70,76,79,65,84,0,66,11,84,89,80,69,
95,73,78,84,54,52,0,66,12,84,89,80,69,95,85,73,
78,84,54,52,0,66,11,84,89,80,69,95,73,78,84,51,
50,0,66,13,84,89,80,69,95,70,73,88,69,68,54,52,
0,66,13,84,89,80,69,95,70,73,88,69,68,51,50,0,
66,10,84,89,80,69,95,66,79,79,76,0,66,12,84,89,
80,69,95,83,84,82,73,78,71,0,66,11,84,89,80,69,
95,71,82,79,85,80,0,66,13,84,89,80,69,95,77,69,
83,83,65,71,69,0,66,11,84,89,80,69,95,66,89,84,
69,83,0,66,12,84,89,80,69,95,85,73,78,84,51,50,
0,66,10,84,89,80,69,95,69,78,85,77,0,66,14,84,
89,80,69,95,83,70,73,88,69,68,51,50,0,66,14,84,
89,80,69,95,83,70,73,88,69,68,54,52,0,66,12,84,
89,80,69,95,83,73,78,84,51,50,0,66,12,84,89,80,
69,95,83,73,78,84,54,52,0,66,15,76,65,66,69,76,
95,79,80,84,73,79,78,65,76,0,66,15,76,65,66,69,
76,95,82,69,81,85,73,82,69,68,0,66,15,76,65,66,
69,76,95,82,69,80,69,65,84,69,68,0,66,6,83,80,
69,69,68,0,66,10,67,79,68,69,95,83,73,90,69,0,
66,13,76,73,84,69,95,82,85,78,84,73,77,69,0,66,
7,83,84,82,73,78,71,0,66,5,67,79,82,68,0,66,
13,83,84,82,73,78,71,95,80,73,69,67,69,0,56,18,
56,3,56,3,56,3,10,11,100,101,115,99,114,105,112,116,
111,114,0,32,1,32,9,32,7,32,2,32,8,32,3,32,
3,32,3,32,4,32,9,32,3,32,5,32,1,32,1,32,
1,32,1,32,7,32,2,32,1,32,2,42,51,24,2,16,
1,32,11,42,36,103,111,111,103,108,101,46,112,114,111,116,
111,98,117,102,46,70,105,108,101,68,101,115,99,114,105,112,
116,111,114,80,114,111,116,111,0,10,5,102,105,108,101,0,
42,13,32,9,24,0,10,5,110,97,109,101,0,16,1,42,
16,32,9,24,0,10,8,112,97,99,107,97,103,101,0,16,
2,42,19,32,9,24,2,10,11,100,101,112,101,110,100,101,
110,99,121,0,16,3,42,55,24,2,16,4,32,11,42,32,
103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46,
68,101,115,99,114,105,112,116,111,114,80,114,111,116,111,0,
10,13,109,101,115,115,97,103,101,95,116,121,112,101,0,42,
56,24,2,16,5,32,11,42,36,103,111,111,103,108,101,46,
112,114,111,116,111,98,117,102,46,69,110,117,109,68,101,115,
99,114,105,112,116,111,114,80,114,111,116,111,0,10,10,101,
110,117,109,95,116,121,112,101,0,42,57,24,2,16,6,32,
11,42,39,103,111,111,103,108,101,46,112,114,111,116,111,98,
117,102,46,83,101,114,118,105,99,101,68,101,115,99,114,105,
112,116,111,114,80,114,111,116,111,0,10,8,115,101,114,118,
105,99,101,0,42,57,24,2,16,7,32,11,42,37,103,111,
111,103,108,101,46,112,114,111,116,111,98,117,102,46,70,105,
101,108,100,68,101,115,99,114,105,112,116,111,114,80,114,111,
116,111,0,10,10,101,120,116,101,110,115,105,111,110,0,42,
46,24,0,16,8,32,11,42,28,103,111,111,103,108,101,46,
112,114,111,116,111,98,117,102,46,70,105,108,101,79,112,116,
105,111,110,115,0,10,8,111,112,116,105,111,110,115,0,42,
58,24,0,16,9,32,11,42,31,103,111,111,103,108,101,46,
112,114,111,116,111,98,117,102,46,83,111,117,114,99,101,67,
111,100,101,73,110,102,111,0,10,17,115,111,117,114,99,101,
95,99,111,100,101,95,105,110,102,111,0,42,13,32,9,24,
0,10,5,110,97,109,101,0,16,1,42,53,24,2,16,2,
32,11,42,37,103,111,111,103,108,101,46,112,114,111,116,111,
98,117,102,46,70,105,101,108,100,68,101,115,99,114,105,112,
116,111,114,80,114,111,116,111,0,10,6,102,105,101,108,100,
0,42,57,24,2,16,6,32,11,42,37,103,111,111,103,108,
101,46,112,114,111,116,111,98,117,102,46,70,105,101,108,100,
68,101,115,99,114,105,112,116,111,114,80,114,111,116,111,0,
10,10,101,120,116,101,110,115,105,111,110,0,42,54,24,2,
16,3,32,11,42,32,103,111,111,103,108,101,46,112,114,111,
116,111,98,117,102,46,68,101,115,99,114,105,112,116,111,114,
80,114,111,116,111,0,10,12,110,101,115,116,101,100,95,116,
121,112,101,0,42,56,24,2,16,4,32,11,42,36,103,111,
111,103,108,101,46,112,114,111,116,111,98,117,102,46,69,110,
117,109,68,101,115,99,114,105,112,116,111,114,80,114,111,116,
111,0,10,10,101,110,117,109,95,116,121,112,101,0,42,73,
24,2,16,5,32,11,42,47,103,111,111,103,108,101,46,112,
114,111,116,111,98,117,102,46,68,101,115,99,114,105,112,116,
111,114,80,114,111,116,111,46,69,120,116,101,110,115,105,111,
110,82,97,110,103,101,0,10,16,101,120,116,101,110,115,105,
111,110,95,114,97,110,103,101,0,42,49,24,0,16,7,32,
11,42,31,103,111,111,103,108,101,46,112,114,111,116,111,98,
117,102,46,77,101,115,115,97,103,101,79,112,116,105,111,110,
115,0,10,8,111,112,116,105,111,110,115,0,42,14,32,5,
24,0,10,6,115,116,97,114,116,0,16,1,42,12,32,5,
24,0,10,4,101,110,100,0,16,2,42,13,32,9,24,0,
10,5,110,97,109,101,0,16,1,42,15,32,5,24,0,10,
7,110,117,109,98,101,114,0,16,3,42,59,24,0,16,4,
32,14,42,43,103,111,111,103,108,101,46,112,114,111,116,111,
98,117,102,46,70,105,101,108,100,68,101,115,99,114,105,112,
116,111,114,80,114,111,116,111,46,76,97,98,101,108,0,10,
6,108,97,98,101,108,0,42,57,24,0,16,5,32,14,42,
42,103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,
46,70,105,101,108,100,68,101,115,99,114,105,112,116,111,114,
80,114,111,116,111,46,84,121,112,101,0,10,5,116,121,112,
101,0,42,18,32,9,24,0,10,10,116,121,112,101,95,110,
97,109,101,0,16,6,42,17,32,9,24,0,10,9,101,120,
116,101,110,100,101,101,0,16,2,42,22,32,9,24,0,10,
14,100,101,102,97,117,108,116,95,118,97,108,117,101,0,16,
7,42,47,24,0,16,8,32,11,42,29,103,111,111,103,108,
101,46,112,114,111,116,111,98,117,102,46,70,105,101,108,100,
79,112,116,105,111,110,115,0,10,8,111,112,116,105,111,110,
115,0,42,13,32,9,24,0,10,5,110,97,109,101,0,16,
1,42,57,24,2,16,2,32,11,42,41,103,111,111,103,108,
101,46,112,114,111,116,111,98,117,102,46,69,110,117,109,86,
97,108,117,101,68,101,115,99,114,105,112,116,111,114,80,114,
111,116,111,0,10,6,118,97,108,117,101,0,42,46,24,0,
16,3,32,11,42,28,103,111,111,103,108,101,46,112,114,111,
116,111,98,117,102,46,69,110,117,109,79,112,116,105,111,110,
115,0,10,8,111,112,116,105,111,110,115,0,42,13,32,9,
24,0,10,5,110,97,109,101,0,16,1,42,15,32,5,24,
0,10,7,110,117,109,98,101,114,0,16,2,42,51,24,0,
16,3,32,11,42,33,103,111,111,103,108,101,46,112,114,111,
116,111,98,117,102,46,69,110,117,109,86,97,108,117,101,79,
112,116,105,111,110,115,0,10,8,111,112,116,105,111,110,115,
0,42,13,32,9,24,0,10,5,110,97,109,101,0,16,1,
42,55,24,2,16,2,32,11,42,38,103,111,111,103,108,101,
46,112,114,111,116,111,98,117,102,46,77,101,116,104,111,100,
68,101,115,99,114,105,112,116,111,114,80,114,111,116,111,0,
10,7,109,101,116,104,111,100,0,42,49,24,0,16,3,32,
11,42,31,103,111,111,103,108,101,46,112,114,111,116,111,98,
117,102,46,83,101,114,118,105,99,101,79,112,116,105,111,110,
115,0,10,8,111,112,116,105,111,110,115,0,42,13,32,9,
24,0,10,5,110,97,109,101,0,16,1,42,19,32,9,24,
0,10,11,105,110,112,117,116,95,116,121,112,101,0,16,2,
42,20,32,9,24,0,10,12,111,117,116,112,117,116,95,116,
121,112,101,0,16,3,42,48,24,0,16,4,32,11,42,30,
103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46,
77,101,116,104,111,100,79,112,116,105,111,110,115,0,10,8,
111,112,116,105,111,110,115,0,42,21,32,9,24,0,10,13,
106,97,118,97,95,112,97,99,107,97,103,101,0,16,1,42,
29,32,9,24,0,10,21,106,97,118,97,95,111,117,116,101,
114,95,99,108,97,115,115,110,97,109,101,0,16,8,42,30,
24,0,16,10,32,8,10,20,106,97,118,97,95,109,117,108,
116,105,112,108,101,95,102,105,108,101,115,0,48,0,42,40,
24,0,16,20,32,8,10,30,106,97,118,97,95,103,101,110,
101,114,97,116,101,95,101,113,117,97,108,115,95,97,110,100,
95,104,97,115,104,0,48,0,42,72,24,0,16,9,32,14,
42,41,103,111,111,103,108,101,46,112,114,111,116,111,98,117,
102,46,70,105,108,101,79,112,116,105,111,110,115,46,79,112,
116,105,109,105,122,101,77,111,100,101,0,10,13,111,112,116,
105,109,105,122,101,95,102,111,114,0,58,6,83,80,69,69,
68,0,42,30,24,0,16,16,32,8,10,20,99,99,95,103,
101,110,101,114,105,99,95,115,101,114,118,105,99,101,115,0,
48,0,42,32,24,0,16,17,32,8,10,22,106,97,118,97,
95,103,101,110,101,114,105,99,95,115,101,114,118,105,99,101,
115,0,48,0,42,30,24,0,16,18,32,8,10,20,112,121,
95,103,101,110,101,114,105,99,95,115,101,114,118,105,99,101,
115,0,48,0,42,68,24,2,16,231,7,32,11,42,36,103,
111,111,103,108,101,46,112,114,111,116,111,98,117,102,46,85,
110,105,110,116,101,114,112,114,101,116,101,100,79,112,116,105,
111,110,0,10,21,117,110,105,110,116,101,114,112,114,101,116,
101,100,95,111,112,116,105,111,110,0,42,34,24,0,16,1,
32,8,10,24,109,101,115,115,97,103,101,95,115,101,116,95,
119,105,114,101,95,102,111,114,109,97,116,0,48,0,42,42,
24,0,16,2,32,8,10,32,110,111,95,115,116,97,110,100,
97,114,100,95,100,101,115,99,114,105,112,116,111,114,95,97,
99,99,101,115,115,111,114,0,48,0,42,68,24,2,16,231,
7,32,11,42,36,103,111,111,103,108,101,46,112,114,111,116,
111,98,117,102,46,85,110,105,110,116,101,114,112,114,101,116,
101,100,79,112,116,105,111,110,0,10,21,117,110,105,110,116,
101,114,112,114,101,116,101,100,95,111,112,116,105,111,110,0,
42,60,24,0,16,1,32,14,42,35,103,111,111,103,108,101,
46,112,114,111,116,111,98,117,102,46,70,105,101,108,100,79,
112,116,105,111,110,115,46,67,84,121,112,101,0,10,6,99,
116,121,112,101,0,58,7,83,84,82,73,78,71,0,42,15,
32,8,24,0,10,7,112,97,99,107,101,100,0,16,2,42,
21,24,0,16,3,32,8,10,11,100,101,112,114,101,99,97,
116,101,100,0,48,0,42,29,32,9,24,0,10,21,101,120,
112,101,114,105,109,101,110,116,97,108,95,109,97,112,95,107,
101,121,0,16,9,42,68,24,2,16,231,7,32,11,42,36,
103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46,
85,110,105,110,116,101,114,112,114,101,116,101,100,79,112,116,
105,111,110,0,10,21,117,110,105,110,116,101,114,112,114,101,
116,101,100,95,111,112,116,105,111,110,0,42,68,24,2,16,
231,7,32,11,42,36,103,111,111,103,108,101,46,112,114,111,
116,111,98,117,102,46,85,110,105,110,116,101,114,112,114,101,
116,101,100,79,112,116,105,111,110,0,10,21,117,110,105,110,
116,101,114,112,114,101,116,101,100,95,111,112,116,105,111,110,
0,42,68,24,2,16,231,7,32,11,42,36,103,111,111,103,
108,101,46,112,114,111,116,111,98,117,102,46,85,110,105,110,
116,101,114,112,114,101,116,101,100,79,112,116,105,111,110,0,
10,21,117,110,105,110,116,101,114,112,114,101,116,101,100,95,
111,112,116,105,111,110,0,42,68,24,2,16,231,7,32,11,
42,36,103,111,111,103,108,101,46,112,114,111,116,111,98,117,
102,46,85,110,105,110,116,101,114,112,114,101,116,101,100,79,
112,116,105,111,110,0,10,21,117,110,105,110,116,101,114,112,
114,101,116,101,100,95,111,112,116,105,111,110,0,42,68,24,
2,16,231,7,32,11,42,36,103,111,111,103,108,101,46,112,
114,111,116,111,98,117,102,46,85,110,105,110,116,101,114,112,
114,101,116,101,100,79,112,116,105,111,110,0,10,21,117,110,
105,110,116,101,114,112,114,101,116,101,100,95,111,112,116,105,
111,110,0,42,60,24,2,16,2,32,11,42,45,103,111,111,
103,108,101,46,112,114,111,116,111,98,117,102,46,85,110,105,
110,116,101,114,112,114,101,116,101,100,79,112,116,105,111,110,
46,78,97,109,101,80,97,114,116,0,10,5,110,97,109,101,
0,42,25,32,9,24,0,10,17,105,100,101,110,116,105,102,
105,101,114,95,118,97,108,117,101,0,16,3,42,27,32,4,
24,0,10,19,112,111,115,105,116,105,118,101,95,105,110,116,
95,118,97,108,117,101,0,16,4,42,27,32,3,24,0,10,
19,110,101,103,97,116,105,118,101,95,105,110,116,95,118,97,
108,117,101,0,16,5,42,21,32,1,24,0,10,13,100,111,
117,98,108,101,95,118,97,108,117,101,0,16,6,42,21,32,
12,24,0,10,13,115,116,114,105,110,103,95,118,97,108,117,
101,0,16,7,42,24,32,9,24,0,10,16,97,103,103,114,
101,103,97,116,101,95,118,97,108,117,101,0,16,8,42,18,
32,9,24,1,10,10,110,97,109,101,95,112,97,114,116,0,
16,1,42,21,32,8,24,1,10,13,105,115,95,101,120,116,
101,110,115,105,111,110,0,16,2,42,59,24,2,16,1,32,
11,42,40,103,111,111,103,108,101,46,112,114,111,116,111,98,
117,102,46,83,111,117,114,99,101,67,111,100,101,73,110,102,
111,46,76,111,99,97,116,105,111,110,0,10,9,108,111,99,
97,116,105,111,110,0,42,13,32,5,24,2,10,5,112,97,
116,104,0,16,1,42,13,32,5,24,2,10,5,115,112,97,
110,0,16,2,26,34,103,111,111,103,108,101,46,112,114,111,
116,111,98,117,102,46,70,105,108,101,68,101,115,99,114,105,
112,116,111,114,83,101,116,0,26,36,103,111,111,103,108,101,
46,112,114,111,116,111,98,117,102,46,70,105,108,101,68,101,
115,99,114,105,112,116,111,114,80,114,111,116,111,0,26,32,
103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46,
68,101,115,99,114,105,112,116,111,114,80,114,111,116,111,0,
26,47,103,111,111,103,108,101,46,112,114,111,116,111,98,117,
102,46,68,101,115,99,114,105,112,116,111,114,80,114,111,116,
111,46,69,120,116,101,110,115,105,111,110,82,97,110,103,101,
0,26,37,103,111,111,103,108,101,46,112,114,111,116,111,98,
117,102,46,70,105,101,108,100,68,101,115,99,114,105,112,116,
111,114,80,114,111,116,111,0,26,36,103,111,111,103,108,101,
46,112,114,111,116,111,98,117,102,46,69,110,117,109,68,101,
115,99,114,105,112,116,111,114,80,114,111,116,111,0,26,41,
103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,46,
69,110,117,109,86,97,108,117,101,68,101,115,99,114,105,112,
116,111,114,80,114,111,116,111,0,26,39,103,111,111,103,108,
101,46,112,114,111,116,111,98,117,102,46,83,101,114,118,105,
99,101,68,101,115,99,114,105,112,116,111,114,80,114,111,116,
111,0,26,38,103,111,111,103,108,101,46,112,114,111,116,111,
98,117,102,46,77,101,116,104,111,100,68,101,115,99,114,105,
112,116,111,114,80,114,111,116,111,0,26,28,103,111,111,103,
108,101,46,112,114,111,116,111,98,117,102,46,70,105,108,101,
79,112,116,105,111,110,115,0,26,31,103,111,111,103,108,101,
46,112,114,111,116,111,98,117,102,46,77,101,115,115,97,103,
101,79,112,116,105,111,110,115,0,26,29,103,111,111,103,108,
101,46,112,114,111,116,111,98,117,102,46,70,105,101,108,100,
79,112,116,105,111,110,115,0,26,28,103,111,111,103,108,101,
46,112,114,111,116,111,98,117,102,46,69,110,117,109,79,112,
116,105,111,110,115,0,26,33,103,111,111,103,108,101,46,112,
114,111,116,111,98,117,102,46,69,110,117,109,86,97,108,117,
101,79,112,116,105,111,110,115,0,26,31,103,111,111,103,108,
101,46,112,114,111,116,111,98,117,102,46,83,101,114,118,105,
99,101,79,112,116,105,111,110,115,0,26,30,103,111,111,103,
108,101,46,112,114,111,116,111,98,117,102,46,77,101,116,104,
111,100,79,112,116,105,111,110,115,0,26,36,103,111,111,103,
108,101,46,112,114,111,116,111,98,117,102,46,85,110,105,110,
116,101,114,112,114,101,116,101,100,79,112,116,105,111,110,0,
26,45,103,111,111,103,108,101,46,112,114,111,116,111,98,117,
102,46,85,110,105,110,116,101,114,112,114,101,116,101,100,79,
112,116,105,111,110,46,78,97,109,101,80,97,114,116,0,26,
31,103,111,111,103,108,101,46,112,114,111,116,111,98,117,102,
46,83,111,117,114,99,101,67,111,100,101,73,110,102,111,0,
26,40,103,111,111,103,108,101,46,112,114,111,116,111,98,117,
102,46,83,111,117,114,99,101,67,111,100,101,73,110,102,111,
46,76,111,99,97,116,105,111,110,0,
};

View File

@@ -1,477 +0,0 @@
#include "map.h"
#include "alloc.h"
#include <stdlib.h>
#include <string.h>
struct _pbcM_ip_slot {
int id;
void * pointer;
int next;
};
struct map_ip {
size_t array_size;
void ** array;
size_t hash_size;
struct _pbcM_ip_slot * slot;
};
struct _pbcM_si_slot {
const char *key;
size_t hash;
int id;
int next;
};
struct map_si {
size_t size;
struct _pbcM_si_slot slot[1];
};
static size_t
calc_hash(const char *name)
{
size_t len = strlen(name);
size_t h = len;
size_t step = (len>>5)+1;
size_t i;
for (i=len; i>=step; i-=step)
h = h ^ ((h<<5)+(h>>2)+(size_t)name[i-1]);
return h;
}
struct map_si *
_pbcM_si_new(struct map_kv * table, int size)
{
size_t sz = sizeof(struct map_si) + (size-1) * sizeof(struct _pbcM_si_slot);
struct map_si * ret = (struct map_si *)malloc(sz);
memset(ret,0,sz);
ret->size = (size_t)size;
int empty = 0;
int i;
for (i=0;i<size;i++) {
size_t hash_full = calc_hash(table[i].pointer);
size_t hash = hash_full % size;
struct _pbcM_si_slot * slot = &ret->slot[hash];
if (slot->key == NULL) {
slot->key = table[i].pointer;
slot->id = table[i].id;
slot->hash = hash_full;
} else {
while(ret->slot[empty].key != NULL) {
++empty;
}
struct _pbcM_si_slot * empty_slot = &ret->slot[empty];
empty_slot->next = slot->next;
slot->next = empty + 1;
empty_slot->id = table[i].id;
empty_slot->key = table[i].pointer;
empty_slot->hash = hash_full;
}
}
return ret;
}
void
_pbcM_si_delete(struct map_si *map)
{
free(map);
}
int
_pbcM_si_query(struct map_si *map, const char *key, int *result)
{
size_t hash_full = calc_hash(key);
size_t hash = hash_full % map->size;
struct _pbcM_si_slot * slot = &map->slot[hash];
for (;;) {
if (slot->hash == hash_full && strcmp(slot->key, key) == 0) {
*result = slot->id;
return 0;
}
if (slot->next == 0) {
return 1;
}
slot = &map->slot[slot->next-1];
}
}
static struct map_ip *
_pbcM_ip_new_hash(struct map_kv * table, int size)
{
struct map_ip * ret = (struct map_ip *)malloc(sizeof(struct map_ip));
ret->array = NULL;
ret->array_size = 0;
ret->hash_size = (size_t)size;
ret->slot = malloc(sizeof(struct _pbcM_ip_slot) * size);
memset(ret->slot,0,sizeof(struct _pbcM_ip_slot) * size);
int empty = 0;
int i;
for (i=0;i<size;i++) {
int hash = ((unsigned)table[i].id) % size;
struct _pbcM_ip_slot * slot = &ret->slot[hash];
if (slot->pointer == NULL) {
slot->pointer = table[i].pointer;
slot->id = table[i].id;
} else {
while(ret->slot[empty].pointer != NULL) {
++empty;
}
struct _pbcM_ip_slot * empty_slot = &ret->slot[empty];
empty_slot->next = slot->next;
slot->next = empty + 1;
empty_slot->id = table[i].id;
empty_slot->pointer = table[i].pointer;
}
}
return ret;
}
struct map_ip *
_pbcM_ip_new(struct map_kv * table, int size)
{
int i;
int max = table[0].id;
if (max > size * 2 || max < 0)
return _pbcM_ip_new_hash(table,size);
for (i=1;i<size;i++) {
if (table[i].id < 0) {
return _pbcM_ip_new_hash(table,size);
}
if (table[i].id > max) {
max = table[i].id;
if (max > size * 2)
return _pbcM_ip_new_hash(table,size);
}
}
struct map_ip * ret = (struct map_ip *)malloc(sizeof(struct map_ip));
ret->hash_size = size;
ret->slot = NULL;
ret->array_size = max + 1;
ret->array = (void **)malloc((max+1) * sizeof(void *));
memset(ret->array,0,(max+1) * sizeof(void *));
for (i=0;i<size;i++) {
ret->array[table[i].id] = table[i].pointer;
}
return ret;
}
void
_pbcM_ip_delete(struct map_ip * map)
{
if (map) {
free(map->array);
free(map->slot);
free(map);
}
}
static void
_inject(struct map_kv * table, struct map_ip *map)
{
if (map->array) {
int n = 0;
int i;
for (i=0;i<(int)map->array_size;i++) {
if (map->array[i]) {
table[n].id = i;
table[n].pointer = map->array[i];
++ n;
}
}
} else {
int i;
for (i=0;i<(int)map->hash_size;i++) {
table[i].id = map->slot[i].id;
table[i].pointer = map->slot[i].pointer;
}
}
}
struct map_ip *
_pbcM_ip_combine(struct map_ip *a, struct map_ip *b)
{
int sz = (int)(a->hash_size + b->hash_size);
struct map_kv * table = malloc(sz * sizeof(struct map_kv));
memset(table , 0 , sz * sizeof(struct map_kv));
_inject(table, a);
_inject(table + a->hash_size, b);
struct map_ip * r = _pbcM_ip_new(table, sz);
free(table);
return r;
}
void *
_pbcM_ip_query(struct map_ip * map, int id)
{
if (map == NULL)
return NULL;
if (map->array) {
if (id>=0 && id<(int)map->array_size)
return map->array[id];
return NULL;
}
int hash = (unsigned)id % map->hash_size;
struct _pbcM_ip_slot * slot = &map->slot[hash];
for (;;) {
if (slot->id == id) {
return slot->pointer;
}
if (slot->next == 0) {
return NULL;
}
slot = &map->slot[slot->next-1];
}
}
struct _pbcM_sp_slot {
const char *key;
size_t hash;
void *pointer;
int next;
};
struct map_sp {
size_t cap;
size_t size;
struct heap *heap;
struct _pbcM_sp_slot * slot;
};
struct map_sp *
_pbcM_sp_new(int max , struct heap *h)
{
struct map_sp * ret = (struct map_sp *)HMALLOC(sizeof(struct map_sp));
int cap = 1;
while (cap < max) {
cap *=2;
}
ret->cap = cap;
ret->size = 0;
ret->slot = (struct _pbcM_sp_slot *)HMALLOC(ret->cap * sizeof(struct _pbcM_sp_slot));
memset(ret->slot,0,sizeof(struct _pbcM_sp_slot) * ret->cap);
ret->heap = h;
return ret;
}
void
_pbcM_sp_delete(struct map_sp *map)
{
if (map && map->heap == NULL) {
_pbcM_free(map->slot);
_pbcM_free(map);
}
}
static void _pbcM_sp_rehash(struct map_sp *map);
static void
_pbcM_sp_insert_hash(struct map_sp *map, const char *key, size_t hash_full, void * value)
{
if (map->cap > map->size) {
size_t hash = hash_full & (map->cap-1);
struct _pbcM_sp_slot * slot = &map->slot[hash];
if (slot->key == NULL) {
slot->key = key;
slot->pointer = value;
slot->hash = hash_full;
} else {
int empty = (hash + 1) & (map->cap-1);
while(map->slot[empty].key != NULL) {
empty = (empty + 1) & (map->cap-1);
}
struct _pbcM_sp_slot * empty_slot = &map->slot[empty];
empty_slot->next = slot->next;
slot->next = empty + 1;
empty_slot->pointer = value;
empty_slot->key = key;
empty_slot->hash = hash_full;
}
map->size++;
return;
}
_pbcM_sp_rehash(map);
_pbcM_sp_insert_hash(map, key, hash_full, value);
}
static void
_pbcM_sp_rehash(struct map_sp *map) {
struct heap * h = map->heap;
struct _pbcM_sp_slot * old_slot = map->slot;
size_t size = map->size;
map->size = 0;
map->cap *= 2;
map->slot = (struct _pbcM_sp_slot *)HMALLOC(sizeof(struct _pbcM_sp_slot)*map->cap);
memset(map->slot,0,sizeof(struct _pbcM_sp_slot)*map->cap);
size_t i;
for (i=0;i<size;i++) {
_pbcM_sp_insert_hash(map, old_slot[i].key, old_slot[i].hash, old_slot[i].pointer);
}
if (h == NULL) {
_pbcM_free(old_slot);
}
}
static void **
_pbcM_sp_query_insert_hash(struct map_sp *map, const char *key, size_t hash_full)
{
size_t hash = hash_full & (map->cap-1);
struct _pbcM_sp_slot * slot = &map->slot[hash];
if (slot->key == NULL) {
if (map->cap <= map->size)
goto _rehash;
slot->key = key;
slot->hash = hash_full;
map->size++;
return &(slot->pointer);
} else {
for (;;) {
if (slot->hash == hash_full && strcmp(slot->key, key) == 0)
return &(slot->pointer);
if (slot->next == 0) {
break;
}
slot = &map->slot[slot->next-1];
}
if (map->cap <= map->size)
goto _rehash;
int empty = (hash + 1) & (map->cap-1);
while(map->slot[empty].key != NULL) {
empty = (empty + 1) & (map->cap-1);
}
struct _pbcM_sp_slot * empty_slot = &map->slot[empty];
empty_slot->next = slot->next;
slot->next = empty + 1;
empty_slot->key = key;
empty_slot->hash = hash_full;
map->size++;
return &(empty_slot->pointer);
}
_rehash:
_pbcM_sp_rehash(map);
return _pbcM_sp_query_insert_hash(map, key, hash_full);
}
void
_pbcM_sp_insert(struct map_sp *map, const char *key, void * value)
{
_pbcM_sp_insert_hash(map,key,calc_hash(key),value);
}
void **
_pbcM_sp_query_insert(struct map_sp *map, const char *key)
{
return _pbcM_sp_query_insert_hash(map,key,calc_hash(key));
}
void *
_pbcM_sp_query(struct map_sp *map, const char *key)
{
if (map == NULL)
return NULL;
size_t hash_full = calc_hash(key);
size_t hash = hash_full & (map->cap -1);
struct _pbcM_sp_slot * slot = &map->slot[hash];
for (;;) {
if (slot->hash == hash_full && strcmp(slot->key, key) == 0) {
return slot->pointer;
}
if (slot->next == 0) {
return NULL;
}
slot = &map->slot[slot->next-1];
}
}
void
_pbcM_sp_foreach(struct map_sp *map, void (*func)(void *p))
{
size_t i;
for (i=0;i<map->cap;i++) {
if (map->slot[i].pointer) {
func(map->slot[i].pointer);
}
}
}
void
_pbcM_sp_foreach_ud(struct map_sp *map, void (*func)(void *p, void *ud), void *ud)
{
size_t i;
for (i=0;i<map->cap;i++) {
if (map->slot[i].pointer) {
func(map->slot[i].pointer,ud);
}
}
}
static int
_find_first(struct map_sp *map)
{
size_t i;
for (i=0;i<map->cap;i++) {
if (map->slot[i].pointer) {
return i;
}
}
return -1;
}
static int
_find_next(struct map_sp *map, const char *key)
{
size_t hash_full = calc_hash(key);
size_t hash = hash_full & (map->cap -1);
struct _pbcM_sp_slot * slot = &map->slot[hash];
for (;;) {
if (slot->hash == hash_full && strcmp(slot->key, key) == 0) {
int i = slot - map->slot + 1;
while(i<map->cap) {
if (map->slot[i].pointer) {
return i;
}
++i;
}
return -1;
}
if (slot->next == 0) {
return -1;
}
slot = &map->slot[slot->next-1];
}
}
void *
_pbcM_sp_next(struct map_sp *map, const char ** key)
{
if (map == NULL) {
*key = NULL;
return NULL;
}
int idx;
if (*key == NULL) {
idx = _find_first(map);
} else {
idx = _find_next(map, *key);
}
if (idx < 0) {
*key = NULL;
return NULL;
}
*key = map->slot[idx].key;
return map->slot[idx].pointer;
}

View File

@@ -1,33 +0,0 @@
#ifndef PROTOBUF_C_MAP_H
#define PROTOBUF_C_MAP_H
#include "alloc.h"
struct map_ip;
struct map_si;
struct map_sp;
struct map_kv {
int id;
void *pointer;
};
struct map_si * _pbcM_si_new(struct map_kv * table, int size);
int _pbcM_si_query(struct map_si *map, const char *key, int *result);
void _pbcM_si_delete(struct map_si *map);
struct map_ip * _pbcM_ip_new(struct map_kv * table, int size);
struct map_ip * _pbcM_ip_combine(struct map_ip * a, struct map_ip * b);
void * _pbcM_ip_query(struct map_ip * map, int id);
void _pbcM_ip_delete(struct map_ip *map);
struct map_sp * _pbcM_sp_new(int max, struct heap *h);
void _pbcM_sp_insert(struct map_sp *map, const char *key, void * value);
void * _pbcM_sp_query(struct map_sp *map, const char *key);
void ** _pbcM_sp_query_insert(struct map_sp *map, const char *key);
void _pbcM_sp_delete(struct map_sp *map);
void _pbcM_sp_foreach(struct map_sp *map, void (*func)(void *p));
void _pbcM_sp_foreach_ud(struct map_sp *map, void (*func)(void *p, void *ud), void *ud);
void * _pbcM_sp_next(struct map_sp *map, const char ** key);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,26 +0,0 @@
#ifndef PROTOBUF_C_PATTERN_H
#define PROTOBUF_C_PATTERN_H
#include "pbc.h"
#include "context.h"
#include "array.h"
struct _pattern_field {
int id;
int offset;
int ptype;
int ctype;
int label;
pbc_var defv;
};
struct pbc_pattern {
struct pbc_env * env;
int count;
struct _pattern_field f[1];
};
struct pbc_pattern * _pbcP_new(struct pbc_env * env, int n);
int _pbcP_unpack_packed(uint8_t *buffer, int size, int ptype, pbc_array array);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,104 +0,0 @@
#ifndef PROTOBUF_C_H
#define PROTOBUF_C_H
#include <stdio.h>
#include <stdint.h>
#define PBC_ARRAY_CAP 64
#define PBC_NOEXIST -1
#define PBC_INT 1
#define PBC_REAL 2
#define PBC_BOOL 3
#define PBC_ENUM 4
#define PBC_STRING 5
#define PBC_MESSAGE 6
#define PBC_FIXED64 7
#define PBC_FIXED32 8
#define PBC_BYTES 9
#define PBC_INT64 10
#define PBC_UINT 11
#define PBC_UNKNOWN 12
#define PBC_REPEATED 128
typedef struct _pbc_array { char _data[PBC_ARRAY_CAP]; } pbc_array[1];
struct pbc_slice {
void *buffer;
int len;
};
struct pbc_pattern;
struct pbc_env;
struct pbc_rmessage;
struct pbc_wmessage;
struct pbc_env * pbc_new(void);
void pbc_delete(struct pbc_env *);
int pbc_register(struct pbc_env *, struct pbc_slice * slice);
int pbc_type(struct pbc_env *, const char * typename , const char * key , const char ** type);
const char * pbc_error(struct pbc_env *);
// callback api
union pbc_value {
struct {
uint32_t low;
uint32_t hi;
} i;
double f;
struct pbc_slice s;
struct {
int id;
const char * name;
} e;
};
typedef void (*pbc_decoder)(void *ud, int type, const char * typename, union pbc_value *v, int id, const char *key);
int pbc_decode(struct pbc_env * env, const char * typename , struct pbc_slice * slice, pbc_decoder f, void *ud);
// message api
struct pbc_rmessage * pbc_rmessage_new(struct pbc_env * env, const char * typename , struct pbc_slice * slice);
void pbc_rmessage_delete(struct pbc_rmessage *);
uint32_t pbc_rmessage_integer(struct pbc_rmessage * , const char *key , int index, uint32_t *hi);
double pbc_rmessage_real(struct pbc_rmessage * , const char *key , int index);
const char * pbc_rmessage_string(struct pbc_rmessage * , const char *key , int index, int *sz);
struct pbc_rmessage * pbc_rmessage_message(struct pbc_rmessage *, const char *key, int index);
int pbc_rmessage_size(struct pbc_rmessage *, const char *key);
int pbc_rmessage_next(struct pbc_rmessage *, const char **key);
struct pbc_wmessage * pbc_wmessage_new(struct pbc_env * env, const char *typename);
void pbc_wmessage_delete(struct pbc_wmessage *);
// for negative integer, pass -1 to hi
int pbc_wmessage_integer(struct pbc_wmessage *, const char *key, uint32_t low, uint32_t hi);
int pbc_wmessage_real(struct pbc_wmessage *, const char *key, double v);
int pbc_wmessage_string(struct pbc_wmessage *, const char *key, const char * v, int len);
struct pbc_wmessage * pbc_wmessage_message(struct pbc_wmessage *, const char *key);
void * pbc_wmessage_buffer(struct pbc_wmessage *, struct pbc_slice * slice);
// array api
int pbc_array_size(pbc_array);
uint32_t pbc_array_integer(pbc_array array, int index, uint32_t *hi);
double pbc_array_real(pbc_array array, int index);
struct pbc_slice * pbc_array_slice(pbc_array array, int index);
void pbc_array_push_integer(pbc_array array, uint32_t low, uint32_t hi);
void pbc_array_push_slice(pbc_array array, struct pbc_slice *);
void pbc_array_push_real(pbc_array array, double v);
struct pbc_pattern * pbc_pattern_new(struct pbc_env * , const char * message, const char *format, ...);
void pbc_pattern_delete(struct pbc_pattern *);
// return unused bytes , -1 for error
int pbc_pattern_pack(struct pbc_pattern *, void *input, struct pbc_slice * s);
// <0 for error
int pbc_pattern_unpack(struct pbc_pattern *, struct pbc_slice * s , void * output);
void pbc_pattern_set_default(struct pbc_pattern * , void *data);
void pbc_pattern_close_arrays(struct pbc_pattern *, void *data);
#endif

View File

@@ -1,252 +0,0 @@
#include "pbc.h"
#include "proto.h"
#include "pattern.h"
#include "map.h"
#include "alloc.h"
#include "stringpool.h"
#include "bootstrap.h"
#include <stdlib.h>
#include <string.h>
const char *
pbc_error(struct pbc_env * p) {
const char *err = p->lasterror;
p->lasterror = "";
return err;
}
struct _message *
_pbcP_get_message(struct pbc_env * p , const char *name) {
return _pbcM_sp_query(p->msgs, name);
}
struct pbc_env *
pbc_new(void) {
struct pbc_env * p = malloc(sizeof(*p));
p->files = _pbcM_sp_new(0 , NULL);
p->enums = _pbcM_sp_new(0 , NULL);
p->msgs = _pbcM_sp_new(0 , NULL);
p->lasterror = "";
_pbcB_init(p);
return p;
}
static void
free_enum(void *p) {
struct _enum * e = p;
_pbcM_ip_delete(e->id);
_pbcM_si_delete(e->name);
free(p);
}
static void
free_stringpool(void *p) {
_pbcS_delete(p);
}
static void
free_msg(void *p) {
struct _message * m = p;
if (m->id)
_pbcM_ip_delete(m->id);
free(m->def);
_pbcM_sp_foreach(m->name, free);
_pbcM_sp_delete(m->name);
free(p);
}
void
pbc_delete(struct pbc_env *p) {
_pbcM_sp_foreach(p->enums, free_enum);
_pbcM_sp_delete(p->enums);
_pbcM_sp_foreach(p->msgs, free_msg);
_pbcM_sp_delete(p->msgs);
_pbcM_sp_foreach(p->files, free_stringpool);
_pbcM_sp_delete(p->files);
free(p);
}
struct _enum *
_pbcP_push_enum(struct pbc_env * p, const char *name, struct map_kv *table, int sz) {
void * check = _pbcM_sp_query(p->enums, name);
if (check)
return NULL;
struct _enum * v = malloc(sizeof(*v));
v->key = name;
v->id = _pbcM_ip_new(table,sz);
v->name = _pbcM_si_new(table,sz);
v->default_v->e.id = table[0].id;
v->default_v->e.name = table[0].pointer;
_pbcM_sp_insert(p->enums, name , v);
return v;
}
void
_pbcP_push_message(struct pbc_env * p, const char *name, struct _field *f , pbc_array queue) {
struct _message * m = _pbcM_sp_query(p->msgs, name);
if (m==NULL) {
m = malloc(sizeof(*m));
m->def = NULL;
m->key = name;
m->id = NULL;
m->name = _pbcM_sp_new(0 , NULL);
m->env = p;
_pbcM_sp_insert(p->msgs, name, m);
}
struct _field * field = malloc(sizeof(*field));
memcpy(field,f,sizeof(*f));
_pbcM_sp_insert(m->name, field->name, field);
pbc_var atom;
atom->m.buffer = field;
if (f->type == PTYPE_MESSAGE || f->type == PTYPE_ENUM) {
_pbcA_push(queue, atom);
}
}
struct _iter {
int count;
struct map_kv * table;
};
static void
_count(void *p, void *ud) {
struct _iter *iter = ud;
iter->count ++;
}
static void
_set_table(void *p, void *ud) {
struct _field * field = p;
struct _iter *iter = ud;
iter->table[iter->count].id = field->id;
iter->table[iter->count].pointer = field;
++iter->count;
}
struct _message *
_pbcP_init_message(struct pbc_env * p, const char *name) {
struct _message * m = _pbcM_sp_query(p->msgs, name);
if (m == NULL) {
m = malloc(sizeof(*m));
m->def = NULL;
m->key = name;
m->id = NULL;
m->name = _pbcM_sp_new(0 , NULL);
m->env = p;
_pbcM_sp_insert(p->msgs, name, m);
return m;
}
if (m->id) {
// extend message, delete old id map.
_pbcM_ip_delete(m->id);
}
struct _iter iter = { 0, NULL };
_pbcM_sp_foreach_ud(m->name, _count, &iter);
iter.table = malloc(iter.count * sizeof(struct map_kv));
iter.count = 0;
_pbcM_sp_foreach_ud(m->name, _set_table, &iter);
m->id = _pbcM_ip_new(iter.table , iter.count);
free(iter.table);
return m;
}
int
_pbcP_message_default(struct _message * m, const char * name, pbc_var defv) {
struct _field * f= _pbcM_sp_query(m->name, name);
if (f==NULL) {
// invalid key
defv->p[0] = NULL;
defv->p[1] = NULL;
return -1;
}
*defv = *(f->default_v);
return f->type;
}
int
_pbcP_type(struct _field * field, const char ** type) {
if (field == NULL) {
return 0;
}
int ret = 0;
switch (field->type) {
case PTYPE_DOUBLE:
case PTYPE_FLOAT:
ret = PBC_REAL;
break;
case PTYPE_INT64:
case PTYPE_SINT64:
ret = PBC_INT64;
break;
case PTYPE_INT32:
case PTYPE_SINT32:
ret = PBC_INT;
break;
case PTYPE_UINT32:
case PTYPE_UINT64:
ret = PBC_UINT;
break;
case PTYPE_FIXED32:
case PTYPE_SFIXED32:
ret = PBC_FIXED32;
break;
case PTYPE_SFIXED64:
case PTYPE_FIXED64:
ret = PBC_FIXED64;
break;
case PTYPE_BOOL:
ret = PBC_BOOL;
break;
case PTYPE_STRING:
ret = PBC_STRING;
break;
case PTYPE_BYTES:
ret = PBC_BYTES;
break;
case PTYPE_ENUM:
ret = PBC_ENUM;
if (type) {
*type = field->type_name.e->key;
}
break;
case PTYPE_MESSAGE:
ret = PBC_MESSAGE;
if (type) {
*type = field->type_name.m->key;
}
break;
default:
return 0;
}
if (field->label == LABEL_REPEATED ||
field->label == LABEL_PACKED) {
ret |= PBC_REPEATED;
}
return ret;
}
int
pbc_type(struct pbc_env * p, const char * typename , const char * key , const char ** type) {
struct _message *m = _pbcP_get_message(p, typename);
if (m==NULL) {
return 0;
}
if (key == NULL) {
return PBC_NOEXIST;
}
struct _field * field = _pbcM_sp_query(m->name, key);
return _pbcP_type(field, type);
}

View File

@@ -1,64 +0,0 @@
#ifndef PROTOBUFC_PROTO_H
#define PROTOBUFC_PROTO_H
#include "pbc.h"
#include "map.h"
#include "array.h"
#include <stdbool.h>
#include <stddef.h>
struct map_ip;
struct map_si;
struct map_sp;
struct _message;
struct _enum;
#define LABEL_OPTIONAL 0
#define LABEL_REQUIRED 1
#define LABEL_REPEATED 2
#define LABEL_PACKED 3
struct _field {
int id;
const char *name;
int type;
int label;
pbc_var default_v;
union {
const char * n;
struct _message * m;
struct _enum * e;
} type_name;
};
struct _message {
const char * key;
struct map_ip * id; // id -> _field
struct map_sp * name; // string -> _field
struct pbc_rmessage * def; // default message
struct pbc_env * env;
};
struct _enum {
const char * key;
struct map_ip * id;
struct map_si * name;
pbc_var default_v;
};
struct pbc_env {
struct map_sp * files; // string -> void *
struct map_sp * enums; // string -> _enum
struct map_sp * msgs; // string -> _message
const char * lasterror;
};
struct _message * _pbcP_init_message(struct pbc_env * p, const char *name);
void _pbcP_push_message(struct pbc_env * p, const char *name, struct _field *f , pbc_array queue);
struct _enum * _pbcP_push_enum(struct pbc_env * p, const char *name, struct map_kv *table, int sz );
int _pbcP_message_default(struct _message * m, const char * name, pbc_var defv);
struct _message * _pbcP_get_message(struct pbc_env * p, const char *name);
int _pbcP_type(struct _field * field, const char **type);
#endif

View File

@@ -1,335 +0,0 @@
#include "pbc.h"
#include "proto.h"
#include "alloc.h"
#include "map.h"
#include "bootstrap.h"
#include "context.h"
#include "stringpool.h"
#include <string.h>
#include <stdlib.h>
static const char *
_concat_name(struct _stringpool *p , const char *prefix , int prefix_sz , const char *name , int name_sz, int *sz) {
if (prefix_sz == 0) {
if (sz) {
*sz = name_sz;
}
return _pbcS_build(p , name, name_sz);
}
char temp[name_sz + prefix_sz + 2];
memcpy(temp,prefix,prefix_sz);
temp[prefix_sz] = '.';
memcpy(temp+prefix_sz+1,name,name_sz);
temp[name_sz + prefix_sz + 1] = '\0';
if (sz) {
*sz = name_sz + prefix_sz + 1;
}
return _pbcS_build(p , temp, name_sz + prefix_sz + 1);
}
static void
_register_enum(struct pbc_env *p, struct _stringpool *pool, struct pbc_rmessage * enum_type, const char *prefix, int prefix_sz) {
int field_count = pbc_rmessage_size(enum_type, "value");
struct map_kv *table = malloc(field_count * sizeof(struct map_kv));
int i;
for (i=0;i<field_count;i++) {
struct pbc_rmessage * value = pbc_rmessage_message(enum_type, "value", i);
int enum_name_sz;
const char *enum_name = pbc_rmessage_string(value , "name" , 0 , &enum_name_sz);
table[i].pointer = (void *)_pbcS_build(pool, enum_name , enum_name_sz);
table[i].id = pbc_rmessage_integer(value , "number", 0 , 0);
}
int name_sz;
const char * name = pbc_rmessage_string(enum_type, "name", 0 , &name_sz);
const char *temp = _concat_name(pool, prefix , prefix_sz , name , name_sz, NULL);
_pbcP_push_enum(p,temp,table,field_count);
free(table);
}
static void
_set_default(struct _stringpool *pool, struct _field *f , int ptype, const char *value, int sz) {
if (value == NULL || sz == 0) {
if (f->type == PTYPE_STRING || f->type == PTYPE_BYTES) {
f->default_v->s.str = "";
f->default_v->s.len = 0;
} else {
f->default_v->integer.low = 0;
f->default_v->integer.hi = 0;
}
return;
}
switch (f->type) {
case PTYPE_DOUBLE:
case PTYPE_FLOAT:
f->default_v->real = strtod(value,NULL);
break;
case PTYPE_STRING:
f->default_v->s.str = _pbcS_build(pool, value , sz);
f->default_v->s.len = sz;
break;
case PTYPE_ENUM:
// enum default value will be converted to f->default_v->e in bootstrap.c : set_field_one()
f->default_v->s.str = value;
f->default_v->s.len = sz;
break;
case PTYPE_BOOL:
if (strcmp(value,"true") == 0) {
f->default_v->integer.low = 1;
} else {
f->default_v->integer.low = 0;
}
f->default_v->integer.hi = 0;
break;
case PTYPE_UINT64:
case PTYPE_INT64:
case PTYPE_SFIXED64:
case PTYPE_SINT64: {
long long v = strtoll(value, NULL, 10);
f->default_v->integer.low = (long) v;
f->default_v->integer.hi = (long)(v >> 32);
break;
}
case PTYPE_INT32:
case PTYPE_FIXED32:
case PTYPE_SFIXED32:
case PTYPE_SINT32:
f->default_v->integer.low = strtol(value, NULL, 10);
if (f->default_v->integer.low < 0) {
f->default_v->integer.hi = -1;
} else {
f->default_v->integer.hi = 0;
}
break;
case PTYPE_UINT32:
f->default_v->integer.low = strtoul(value, NULL, 10);
f->default_v->integer.hi = 0;
break;
case PTYPE_BYTES:
case PTYPE_MESSAGE:
// bytes and message types have no default value
f->default_v->m.buffer = 0;
f->default_v->m.len = 0;
break;
default:
f->default_v->integer.low = 0;
f->default_v->integer.hi = 0;
break;
}
}
static void
_register_field(struct pbc_rmessage * field, struct _field * f, struct _stringpool *pool) {
f->id = pbc_rmessage_integer(field, "number", 0 , 0);
f->type = pbc_rmessage_integer(field, "type", 0 , 0); // enum
f->label = pbc_rmessage_integer(field, "label", 0, 0) - 1; // LABEL_OPTIONAL = 0
if (pbc_rmessage_size(field , "options") > 0) {
struct pbc_rmessage * options = pbc_rmessage_message(field, "options" , 0);
int packed = pbc_rmessage_integer(options , "packed" , 0 , NULL);
if (packed) {
f->label = LABEL_PACKED;
}
}
f->type_name.n = pbc_rmessage_string(field, "type_name", 0 , NULL) +1; // abandon prefix '.'
int vsz;
const char * default_value = pbc_rmessage_string(field, "default_value", 0 , &vsz);
_set_default(pool , f , f->type, default_value , vsz);
}
static void
_register_extension(struct pbc_env *p, struct _stringpool *pool , const char * prefix, int prefix_sz, struct pbc_rmessage * msg, pbc_array queue) {
int extension_count = pbc_rmessage_size(msg , "extension");
if (extension_count <= 0)
return;
int i;
const char * last = NULL;
for (i=0;i<extension_count;i++) {
struct pbc_rmessage * extension = pbc_rmessage_message(msg, "extension", i);
int field_name_sz = 0;
struct _field f;
const char * field_name = pbc_rmessage_string(extension , "name" , 0, &field_name_sz);
f.name = _concat_name(pool, prefix, prefix_sz, field_name, field_name_sz, NULL);
_register_field(extension, &f , pool);
const char * extendee = pbc_rmessage_string(extension , "extendee" , 0, NULL);
_pbcP_push_message(p, extendee + 1 , &f , queue);
if (last == NULL) {
last = extendee;
} else if (strcmp(extendee,last) != 0) {
_pbcP_init_message(p, last+1);
last = extendee;
}
}
_pbcP_init_message(p, last+1);
}
static void
_register_message(struct pbc_env *p, struct _stringpool *pool, struct pbc_rmessage * message_type, const char *prefix, int prefix_sz, pbc_array queue) {
int name_sz;
const char * name = pbc_rmessage_string(message_type, "name", 0 , &name_sz);
int sz = 0;
const char *temp = _concat_name(pool, prefix , prefix_sz , name , name_sz, &sz);
int field_count = pbc_rmessage_size(message_type, "field");
int i;
for (i=0;i<field_count;i++) {
struct pbc_rmessage * field = pbc_rmessage_message(message_type, "field" , i);
struct _field f;
int field_name_sz;
const char * field_name = pbc_rmessage_string(field, "name", 0 , &field_name_sz);
f.name = _pbcS_build(pool,field_name,field_name_sz);
_register_field(field, &f , pool);
_pbcP_push_message(p, temp , &f , queue);
}
_pbcP_init_message(p, temp);
_register_extension(p, pool, temp, sz,message_type, queue);
// nested enum
int enum_count = pbc_rmessage_size(message_type, "enum_type");
for (i=0;i<enum_count;i++) {
struct pbc_rmessage * enum_type = pbc_rmessage_message(message_type, "enum_type", i);
_register_enum(p, pool, enum_type, temp, sz);
}
// nested type
int message_count = pbc_rmessage_size(message_type, "nested_type");
for (i=0;i<message_count;i++) {
struct pbc_rmessage * nested_type = pbc_rmessage_message(message_type, "nested_type", i);
_register_message(p, pool, nested_type, temp, sz, queue);
}
}
static void
_register(struct pbc_env *p, struct pbc_rmessage * file, struct _stringpool *pool) {
int package_sz;
const char *package = pbc_rmessage_string(file, "package", 0, &package_sz);
pbc_array queue;
_pbcA_open(queue);
int enum_count = pbc_rmessage_size(file, "enum_type");
int i;
for (i=0;i<enum_count;i++) {
struct pbc_rmessage * enum_type = pbc_rmessage_message(file, "enum_type", i);
_register_enum(p, pool , enum_type, package, package_sz);
}
int message_count = pbc_rmessage_size(file, "message_type");
for (i=0;i<message_count;i++) {
struct pbc_rmessage * message_type = pbc_rmessage_message(file, "message_type", i);
_register_message(p, pool, message_type, package, package_sz, queue);
}
_register_extension(p, pool, package, package_sz, file , queue);
_pbcB_register_fields(p, queue);
_pbcA_close(queue);
}
#define CHECK_FILE_OK 0
#define CHECK_FILE_EXIST 1
#define CHECK_FILE_DEPENDENCY 2
static int
_check_file_name(struct pbc_env * p , struct pbc_rmessage * file, const char ** fname) {
const char * filename = pbc_rmessage_string(file, "name", 0, NULL);
// printf("reg :%s\n",filename);
if (_pbcM_sp_query(p->files, filename)) {
return CHECK_FILE_EXIST;
}
int sz = pbc_rmessage_size(file, "dependency");
int i;
for (i=0;i<sz;i++) {
const char *dname = pbc_rmessage_string(file,"dependency",i,NULL);
// printf("dependency :%s\n",dname);
if (_pbcM_sp_query(p->files, dname) == NULL) {
return CHECK_FILE_DEPENDENCY;
}
}
*fname = filename;
return CHECK_FILE_OK;
}
static int
_register_no_dependency(struct pbc_env * p,struct pbc_rmessage ** files , int n ) {
int r = 0;
int i;
for (i=0;i<n;i++) {
if (files[i] == NULL)
continue;
const char *filename = NULL;
int err = _check_file_name(p, files[i], &filename);
switch(err) {
case CHECK_FILE_EXIST:
break;
case CHECK_FILE_DEPENDENCY:
++r;
break;
case CHECK_FILE_OK: {
struct _stringpool *pool = _pbcS_new();
filename = _pbcS_build(pool, filename , strlen(filename));
_pbcM_sp_insert(p->files , filename, pool);
_register(p,files[i],pool);
files[i] = NULL;
}
break;
}
}
return r;
}
int
pbc_register(struct pbc_env * p, struct pbc_slice *slice) {
struct pbc_rmessage * message = pbc_rmessage_new(p, "google.protobuf.FileDescriptorSet", slice);
if (message == NULL) {
p->lasterror = "register open google.protobuf.FileDescriptorSet fail";
return 1;
}
int n = pbc_rmessage_size(message, "file");
struct pbc_rmessage * files[n];
int i;
if (n == 0) {
p->lasterror = "register empty";
goto _error;
}
for (i=0;i<n;i++) {
files[i] = pbc_rmessage_message(message, "file", i);
if (files[i] == NULL) {
p->lasterror = "register open fail";
goto _error;
}
}
int r = n;
do {
int rr = _register_no_dependency(p,files , n);
if (rr == r) {
p->lasterror = "register dependency error";
goto _error;
}
r = rr;
} while (r>0);
pbc_rmessage_delete(message);
return 0;
_error:
pbc_rmessage_delete(message);
return 1;
}

View File

@@ -1,455 +0,0 @@
#include "pbc.h"
#include "alloc.h"
#include "map.h"
#include "context.h"
#include "proto.h"
#include "pattern.h"
#include "varint.h"
#include <stddef.h>
#include <string.h>
struct pbc_rmessage {
struct _message * msg;
struct map_sp * index; // key -> struct value *
struct heap * heap;
};
union _var {
pbc_var var;
pbc_array array;
struct pbc_rmessage message;
} ;
struct value {
struct _field * type;
union _var v;
};
int
pbc_rmessage_next(struct pbc_rmessage *m, const char **key) {
struct value * v = _pbcM_sp_next(m->index, key);
if (*key == NULL) {
return 0;
}
return _pbcP_type(v->type, NULL);
}
#define SIZE_VAR (offsetof(struct value, v) + sizeof(pbc_var))
#define SIZE_ARRAY (offsetof(struct value, v) + sizeof(pbc_array))
#define SIZE_MESSAGE (offsetof(struct value, v) + sizeof(struct pbc_rmessage))
static struct value *
read_string(struct heap *h, struct atom *a,struct _field *f, uint8_t *buffer) {
const char * temp = (const char *) (buffer + a->v.s.start);
int len = a->v.s.end - a->v.s.start;
if (len > 0 && temp[len-1] == '\0') {
struct value * v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->s.str = temp;
v->v.var->s.len = len;
return v;
} else {
struct value * v = _pbcH_alloc(h, SIZE_VAR + len + 1);
memcpy(((char *)v) + SIZE_VAR , temp, len);
*(((char *)v) + SIZE_VAR + len) = '\0';
v->v.var->s.str = ((char *)v) + SIZE_VAR;
v->v.var->s.len = len;
return v;
}
}
static void
read_string_var(struct heap *h, pbc_var var,struct atom *a,struct _field *f,uint8_t *buffer) {
const char * temp = (const char *) (buffer + a->v.s.start);
int len = a->v.s.end - a->v.s.start;
if (len == 0) {
var->s.str = "";
var->s.len = 0;
}
else if (temp[len-1] == '\0') {
var->s.str = temp;
var->s.len = len;
} else {
char * temp2 = _pbcH_alloc(h, len + 1);
memcpy(temp2, temp, len);
temp2[len]='\0';
var->s.str = temp2;
var->s.len = -len;
}
}
static void _pbc_rmessage_new(struct pbc_rmessage * ret , struct _message * type , void *buffer, int size, struct heap *h);
static struct value *
read_value(struct heap *h, struct _field *f, struct atom * a, uint8_t *buffer) {
struct value * v;
switch (f->type) {
case PTYPE_DOUBLE:
CHECK_BIT64(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->real = read_double(a);
break;
case PTYPE_FLOAT:
CHECK_BIT32(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->real = (double) read_float(a);
break;
case PTYPE_ENUM:
CHECK_VARINT(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->e.id = a->v.i.low;
v->v.var->e.name = _pbcM_ip_query(f->type_name.e->id , a->v.i.low);
break;
case PTYPE_INT64:
case PTYPE_UINT64:
case PTYPE_INT32:
case PTYPE_UINT32:
case PTYPE_BOOL:
CHECK_VARINT(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->integer = a->v.i;
break;
case PTYPE_FIXED32:
case PTYPE_SFIXED32:
CHECK_BIT32(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->integer = a->v.i;
break;
case PTYPE_FIXED64:
case PTYPE_SFIXED64:
CHECK_BIT64(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->integer = a->v.i;
break;
case PTYPE_SINT32:
CHECK_VARINT(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->integer = a->v.i;
_pbcV_dezigzag32(&(v->v.var->integer));
break;
case PTYPE_SINT64:
CHECK_VARINT(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->integer = a->v.i;
_pbcV_dezigzag64(&(v->v.var->integer));
break;
case PTYPE_STRING:
CHECK_LEND(a,NULL);
v = read_string(h,a,f,buffer);
break;
case PTYPE_BYTES:
CHECK_LEND(a,NULL);
v = _pbcH_alloc(h, SIZE_VAR);
v->v.var->s.str = (const char *)(buffer + a->v.s.start);
v->v.var->s.len = a->v.s.end - a->v.s.start;
break;
case PTYPE_MESSAGE:
CHECK_LEND(a,NULL);
v = _pbcH_alloc(h, SIZE_MESSAGE);
_pbc_rmessage_new(&(v->v.message), f->type_name.m ,
buffer + a->v.s.start ,
a->v.s.end - a->v.s.start,h);
break;
default:
return NULL;
}
v->type = f;
return v;
}
static void
push_value_packed(struct _message * type, pbc_array array, struct _field *f, struct atom * aa, uint8_t *buffer) {
int n = _pbcP_unpack_packed((uint8_t *)buffer + aa->v.s.start, aa->v.s.end - aa->v.s.start,
f->type , array);
if (n<=0) {
// todo : error
type->env->lasterror = "Unpack packed field error";
return;
}
if (f->type == PTYPE_ENUM) {
int i;
for (i=0;i<n;i++) {
union _pbc_var * v = _pbcA_index_p(array, i);
int id = v->integer.low;
v->e.id = id;
v->e.name = _pbcM_ip_query(f->type_name.e->id , id);
}
}
}
static void
push_value_array(struct heap *h, pbc_array array, struct _field *f, struct atom * a, uint8_t *buffer) {
pbc_var v;
switch (f->type) {
case PTYPE_DOUBLE:
v->real = read_double(a);
break;
case PTYPE_FLOAT:
v->real = (double) read_float(a);
break;
case PTYPE_ENUM:
v->e.id = a->v.i.low;
v->e.name = _pbcM_ip_query(f->type_name.e->id , a->v.i.low);
break;
case PTYPE_INT64:
case PTYPE_UINT64:
case PTYPE_INT32:
case PTYPE_UINT32:
case PTYPE_FIXED32:
case PTYPE_FIXED64:
case PTYPE_SFIXED32:
case PTYPE_SFIXED64:
case PTYPE_BOOL:
v->integer = a->v.i;
break;
case PTYPE_SINT32:
v->integer = a->v.i;
_pbcV_dezigzag32(&(v->integer));
break;
case PTYPE_SINT64:
v->integer = a->v.i;
_pbcV_dezigzag64(&(v->integer));
break;
case PTYPE_STRING:
CHECK_LEND(a, );
read_string_var(h,v,a,f,buffer);
break;
case PTYPE_BYTES:
CHECK_LEND(a, );
v->s.str = (const char *)(buffer + a->v.s.start);
v->s.len = a->v.s.end - a->v.s.start;
break;
case PTYPE_MESSAGE: {
CHECK_LEND(a, );
struct pbc_rmessage message;
_pbc_rmessage_new(&message, f->type_name.m ,
buffer + a->v.s.start ,
a->v.s.end - a->v.s.start,h);
if (message.msg == NULL) {
return;
}
v->p[0] = message.msg;
v->p[1] = message.index;
break;
}
default:
return;
}
_pbcA_push(array,v);
}
static void
_pbc_rmessage_new(struct pbc_rmessage * ret , struct _message * type , void *buffer, int size , struct heap *h) {
if (size == 0) {
ret->msg = type;
ret->index = _pbcM_sp_new(0 , h);
ret->heap = h;
return;
}
pbc_ctx _ctx;
int count = _pbcC_open(_ctx,buffer,size);
if (count <= 0) {
type->env->lasterror = "rmessage decode context error";
memset(ret , 0, sizeof(*ret));
return;
}
struct context * ctx = (struct context *)_ctx;
ret->msg = type;
ret->index = _pbcM_sp_new(count, h);
ret->heap = h;
int i;
for (i=0;i<ctx->number;i++) {
int id = ctx->a[i].wire_id >> 3;
struct _field * f = _pbcM_ip_query(type->id , id);
if (f) {
if (f->label == LABEL_REPEATED || f->label == LABEL_PACKED) {
struct value * v;
void ** vv = _pbcM_sp_query_insert(ret->index, f->name);
if (*vv == NULL) {
v = _pbcH_alloc(h, SIZE_ARRAY);
v->type = f;
_pbcA_open_heap(v->v.array,ret->heap);
*vv = v;
} else {
v= *vv;
}
if (f->label == LABEL_PACKED) {
push_value_packed(type, v->v.array , f , &(ctx->a[i]), buffer);
if (pbc_array_size(v->v.array) == 0) {
type->env->lasterror = "rmessage decode packed data error";
*vv = NULL;
}
} else {
push_value_array(h,v->v.array , f, &(ctx->a[i]), buffer);
if (pbc_array_size(v->v.array) == 0) {
type->env->lasterror = "rmessage decode repeated data error";
*vv = NULL;
}
}
} else {
struct value * v = read_value(h, f, &(ctx->a[i]), buffer);
if (v) {
_pbcM_sp_insert(ret->index, f->name, v);
} else {
type->env->lasterror = "rmessage decode data error";
}
}
}
}
_pbcC_close(_ctx);
}
struct pbc_rmessage *
pbc_rmessage_new(struct pbc_env * env, const char * typename , struct pbc_slice * slice) {
struct _message * msg = _pbcP_get_message(env, typename);
if (msg == NULL) {
env->lasterror = "Proto not found";
return NULL;
}
struct pbc_rmessage temp;
struct heap * h = _pbcH_new(slice->len);
_pbc_rmessage_new(&temp, msg , slice->buffer, slice->len , h);
if (temp.msg == NULL) {
_pbcH_delete(h);
return NULL;
}
struct pbc_rmessage *m = _pbcH_alloc(temp.heap, sizeof(*m));
*m = temp;
return m;
}
void
pbc_rmessage_delete(struct pbc_rmessage * m) {
if (m) {
_pbcH_delete(m->heap);
}
}
const char *
pbc_rmessage_string(struct pbc_rmessage * m , const char *key , int index, int *sz) {
struct value * v = _pbcM_sp_query(m->index,key);
int type = 0;
pbc_var var;
if (v == NULL) {
type = _pbcP_message_default(m->msg, key, var);
} else {
if (v->type->label == LABEL_REPEATED || v->type->label == LABEL_PACKED) {
_pbcA_index(v->v.array, index, var);
} else {
var[0] = v->v.var[0];
}
type = v->type->type;
}
if (type == PTYPE_ENUM) {
if (sz) {
*sz = strlen(var->e.name);
}
return var->e.name;
}
if (sz) {
int len = var->s.len;
if (len<0) {
len = - len;
}
*sz = len;
}
return var->s.str;
}
uint32_t
pbc_rmessage_integer(struct pbc_rmessage *m , const char *key , int index, uint32_t *hi) {
struct value * v = _pbcM_sp_query(m->index,key);
pbc_var var;
int type = 0;
if (v == NULL) {
type = _pbcP_message_default(m->msg, key, var);
} else {
if (v->type->label == LABEL_REPEATED || v->type->label == LABEL_PACKED) {
_pbcA_index(v->v.array, index, var);
} else {
var[0] = v->v.var[0];
}
type = v->type->type;
}
if (type == PTYPE_ENUM) {
if (hi) {
*hi = 0;
}
return var->e.id;
}
if (hi) {
*hi = var->integer.hi;
}
return var->integer.low;
}
double
pbc_rmessage_real(struct pbc_rmessage * m, const char *key , int index) {
struct value * v = _pbcM_sp_query(m->index,key);
pbc_var var;
if (v == NULL) {
_pbcP_message_default(m->msg, key, var);
} else {
if (v->type->label == LABEL_REPEATED || v->type->label == LABEL_PACKED) {
_pbcA_index(v->v.array, index, var);
} else {
return v->v.var->real;
}
}
return var->real;
}
struct pbc_rmessage *
pbc_rmessage_message(struct pbc_rmessage * rm, const char *key, int index) {
struct value * v = _pbcM_sp_query(rm->index,key);
if (v == NULL) {
struct _field * f = _pbcM_sp_query(rm->msg->name, key);
if (f == NULL) {
rm->msg->env->lasterror = "Invalid key for sub-message";
// invalid key
return NULL;
}
struct _message * m = f->type_name.m;
if (m->def == NULL) {
// m->def will be free at the end (pbc_delete).
m->def = malloc(sizeof(struct pbc_rmessage));
m->def->msg = m;
m->def->index = NULL;
}
return m->def;
} else {
if (v->type->label == LABEL_REPEATED) {
return _pbcA_index_p(v->v.array,index);
} else {
return &(v->v.message);
}
}
}
int
pbc_rmessage_size(struct pbc_rmessage *m, const char *key) {
struct value * v = _pbcM_sp_query(m->index,key);
if (v == NULL) {
return 0;
}
if (v->type->label == LABEL_REPEATED || v->type->label == LABEL_PACKED) {
return pbc_array_size(v->v.array);
} else {
return 1;
}
}

View File

@@ -1,60 +0,0 @@
#include "alloc.h"
#include <stdlib.h>
#include <string.h>
#define PAGE_SIZE 256
struct _stringpool {
char * buffer;
size_t len;
struct _stringpool *next;
};
struct _stringpool *
_pbcS_new(void) {
struct _stringpool * ret = (struct _stringpool *)malloc(sizeof(struct _stringpool) + PAGE_SIZE);
ret->buffer = (char *)(ret + 1);
ret->len = 0;
ret->next = NULL;
return ret;
}
void
_pbcS_delete(struct _stringpool *pool) {
while(pool) {
struct _stringpool *next = pool->next;
free(pool);
pool = next;
}
}
const char *
_pbcS_build(struct _stringpool *pool, const char * str , int sz) {
size_t s = sz + 1;
if (s < PAGE_SIZE - pool->len) {
char * ret = pool->buffer + pool->len;
memcpy(pool->buffer + pool->len, str, s);
pool->len += s;
return ret;
}
if (s > PAGE_SIZE) {
struct _stringpool * next = (struct _stringpool *)malloc(sizeof(struct _stringpool) + s);
next->buffer = (char *)(next + 1);
memcpy(next->buffer, str, s);
next->len = s;
next->next = pool->next;
pool->next = next;
return next->buffer;
}
struct _stringpool *next = (struct _stringpool *)malloc(sizeof(struct _stringpool) + PAGE_SIZE);
next->buffer = pool->buffer;
next->next = pool->next;
next->len = pool->len;
pool->next = next;
pool->buffer = (char *)(next + 1);
memcpy(pool->buffer, str, s);
pool->len = s;
return pool->buffer;
}

View File

@@ -1,10 +0,0 @@
#ifndef PROTOBUF_C_STRINGPOOL_H
#define PROTOBUF_C_STRINGPOOL_H
struct _stringpool;
struct _stringpool * _pbcS_new(void);
void _pbcS_delete(struct _stringpool *pool);
const char * _pbcS_build(struct _stringpool *pool, const char * str , int sz);
#endif

View File

@@ -1,30 +0,0 @@
require "protobuf"
addr = io.open("addressbook.pb","rb")
buffer = addr:read "*a"
addr:close()
protobuf.register(buffer)
addressbook = {
name = "Alice",
id = 12345,
phone = {
{ number = "1301234567" },
{ number = "87654321", type = "WORK" },
}
}
code = protobuf.encode("tutorial.Person", addressbook)
decode = protobuf.decode("tutorial.Person" , code)
print(decode.name)
print(decode.id)
for _,v in ipairs(decode.phone) do
print("\t"..v.number, v.type)
end
phonebuf = protobuf.pack("tutorial.Person.PhoneNumber number","87654321")
buffer = protobuf.pack("tutorial.Person name id phone", "Alice", 123, { phonebuf })
print(protobuf.unpack("tutorial.Person name id phone", buffer))

View File

@@ -1,110 +0,0 @@
#include "varint.h"
#include "pbc.h"
#include <stdint.h>
inline int
_pbcV_encode32(uint32_t number, uint8_t buffer[10])
{
if (number < 0x80) {
buffer[0] = (uint8_t) number ;
return 1;
}
buffer[0] = (uint8_t) (number | 0x80 );
if (number < 0x4000) {
buffer[1] = (uint8_t) (number >> 7 );
return 2;
}
buffer[1] = (uint8_t) ((number >> 7) | 0x80 );
if (number < 0x200000) {
buffer[2] = (uint8_t) (number >> 14);
return 3;
}
buffer[2] = (uint8_t) ((number >> 14) | 0x80 );
if (number < 0x10000000) {
buffer[3] = (uint8_t) (number >> 21);
return 4;
}
buffer[3] = (uint8_t) ((number >> 21) | 0x80 );
buffer[4] = (uint8_t) (number >> 28);
return 5;
}
int
_pbcV_encode(uint64_t number, uint8_t buffer[10])
{
if ((number & 0xffffffff) == number) {
return _pbcV_encode32((uint32_t)number , buffer);
}
int i = 0;
do {
buffer[i] = (uint8_t)(number | 0x80);
number >>= 7;
++i;
} while (number >= 0x80);
buffer[i] = (uint8_t)number;
return i+1;
}
int
_pbcV_decode(uint8_t buffer[10], struct longlong *result) {
if (!(buffer[0] & 0x80)) {
result->low = buffer[0];
result->hi = 0;
return 1;
}
uint32_t r = buffer[0] & 0x7f;
int i;
for (i=1;i<4;i++) {
r |= ((buffer[i]&0x7f) << (7*i));
if (!(buffer[i] & 0x80)) {
result->low = r;
result->hi = 0;
return i+1;
}
}
uint64_t lr = 0;
for (i=4;i<10;i++) {
lr |= ((buffer[i] & 0x7f) << (7*(i-4)));
if (!(buffer[i] & 0x80)) {
result->hi = (uint32_t)(lr >> 4);
result->low = r | (((uint32_t)lr & 0xf) << 28);
return i+1;
}
}
result->low = 0;
result->hi = 0;
return 10;
}
int
_pbcV_zigzag32(int32_t n, uint8_t buffer[10])
{
n = (n << 1) ^ (n >> 31);
return _pbcV_encode32(n,buffer);
}
int
_pbcV_zigzag(int64_t n, uint8_t buffer[10])
{
n = (n << 1) ^ (n >> 63);
return _pbcV_encode(n,buffer);
}
void
_pbcV_dezigzag64(struct longlong *r)
{
uint32_t low = r->low;
r->low = ((low >> 1) | ((r->hi & 1) << 31)) ^ - (low & 1);
r->hi = (r->hi >> 1) ^ - (low & 1);
}
void
_pbcV_dezigzag32(struct longlong *r)
{
uint32_t low = r->low;
r->low = (low >> 1) ^ - (low & 1);
r->hi = -(low >> 31);
}

View File

@@ -1,20 +0,0 @@
#ifndef PROTOBUF_C_VARINT_H
#define PROTOBUF_C_VARINT_H
#include <stdint.h>
struct longlong {
uint32_t low;
uint32_t hi;
};
int _pbcV_encode32(uint32_t number, uint8_t buffer[10]);
int _pbcV_encode(uint64_t number, uint8_t buffer[10]);
int _pbcV_zigzag32(int32_t number, uint8_t buffer[10]);
int _pbcV_zigzag(int64_t number, uint8_t buffer[10]);
int _pbcV_decode(uint8_t buffer[10], struct longlong *result);
void _pbcV_dezigzag64(struct longlong *r);
void _pbcV_dezigzag32(struct longlong *r);
#endif

View File

@@ -1,509 +0,0 @@
#include "pbc.h"
#include "context.h"
#include "alloc.h"
#include "varint.h"
#include "map.h"
#include "proto.h"
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>
#define WMESSAGE_SIZE 64
struct pbc_wmessage {
struct _message *type;
uint8_t * buffer;
uint8_t * ptr;
uint8_t * endptr;
pbc_array sub;
struct map_sp *packed;
struct heap * heap;
};
struct _packed {
int id;
int ptype;
pbc_array data;
};
static struct pbc_wmessage *
_wmessage_new(struct heap *h, struct _message *msg) {
struct pbc_wmessage * m = _pbcH_alloc(h, sizeof(*m));
m->type = msg;
m->buffer = _pbcH_alloc(h, WMESSAGE_SIZE);
m->ptr = m->buffer;
m->endptr = m->buffer + WMESSAGE_SIZE;
_pbcA_open_heap(m->sub, h);
m->packed = NULL;
m->heap = h;
return m;
}
struct pbc_wmessage *
pbc_wmessage_new(struct pbc_env * env, const char *typename) {
struct _message * msg = _pbcP_get_message(env, typename);
if (msg == NULL)
return NULL;
struct heap *h = _pbcH_new(0);
return _wmessage_new(h, msg);
}
void
pbc_wmessage_delete(struct pbc_wmessage *m) {
if (m) {
_pbcH_delete(m->heap);
}
}
static void
_expand(struct pbc_wmessage *m, int sz) {
if (m->ptr + sz > m->endptr) {
int cap = m->endptr - m->buffer;
sz = m->ptr + sz - m->buffer;
do {
cap = cap * 2;
} while ( sz > cap ) ;
int old_size = m->ptr - m->buffer;
uint8_t * buffer = _pbcH_alloc(m->heap, cap);
memcpy(buffer, m->buffer, old_size);
m->ptr = buffer + (m->ptr - m->buffer);
m->endptr = buffer + cap;
m->buffer = buffer;
}
}
static struct _packed *
_get_packed(struct pbc_wmessage *m , struct _field *f , const char *key) {
if (m->packed == NULL) {
m->packed = _pbcM_sp_new(4, m->heap);
}
void ** v = _pbcM_sp_query_insert(m->packed , key);
if (*v == NULL) {
*v = _pbcH_alloc(m->heap, sizeof(struct _packed));
struct _packed *p = *v;
p->id = f->id;
p->ptype = f->type;
_pbcA_open_heap(p->data, m->heap);
return p;
}
return *v;
}
static void
_packed_integer(struct pbc_wmessage *m, struct _field *f, const char *key , uint32_t low, uint32_t hi) {
struct _packed * packed = _get_packed(m,f,key);
pbc_var var;
var->integer.low = low;
var->integer.hi = hi;
_pbcA_push(packed->data , var);
}
static void
_packed_real(struct pbc_wmessage *m, struct _field *f, const char *key , double v) {
struct _packed * packed = _get_packed(m,f,key);
pbc_var var;
var->real = v;
_pbcA_push(packed->data , var);
}
static inline void
int64_encode(uint32_t low, uint32_t hi , uint8_t * buffer) {
buffer[0] = (uint8_t)(low & 0xff);
buffer[1] = (uint8_t)(low >> 8 & 0xff);
buffer[2] = (uint8_t)(low >> 16 & 0xff);
buffer[3] = (uint8_t)(low >> 24 & 0xff);
buffer[4] = (uint8_t)(hi & 0xff);
buffer[5] = (uint8_t)(hi >> 8 & 0xff);
buffer[6] = (uint8_t)(hi >> 16 & 0xff);
buffer[7] = (uint8_t)(hi >> 24 & 0xff);
}
static inline void
int32_encode(uint32_t low, uint8_t * buffer) {
buffer[0] = (uint8_t)(low & 0xff);
buffer[1] = (uint8_t)(low >> 8 & 0xff);
buffer[2] = (uint8_t)(low >> 16 & 0xff);
buffer[3] = (uint8_t)(low >> 24 & 0xff);
}
int
pbc_wmessage_integer(struct pbc_wmessage *m, const char *key, uint32_t low, uint32_t hi) {
struct _field * f = _pbcM_sp_query(m->type->name,key);
if (f==NULL) {
// todo : error
m->type->env->lasterror = "wmessage_interger query key error";
return -1;
}
if (f->label == LABEL_PACKED) {
_packed_integer(m , f, key , low, hi);
return 0;
}
if (f->label == LABEL_OPTIONAL) {
if (f->type == PTYPE_ENUM) {
if (low == f->default_v->e.id)
return 0;
} else {
if (low == f->default_v->integer.low &&
hi == f->default_v->integer.hi) {
return 0;
}
}
}
int id = f->id << 3;
_expand(m,20);
switch (f->type) {
case PTYPE_INT64:
case PTYPE_UINT64:
case PTYPE_INT32:
id |= WT_VARINT;
m->ptr += _pbcV_encode32(id, m->ptr);
m->ptr += _pbcV_encode((uint64_t)low | (uint64_t)hi << 32 , m->ptr);
break;
case PTYPE_UINT32:
case PTYPE_ENUM:
case PTYPE_BOOL:
id |= WT_VARINT;
m->ptr += _pbcV_encode32(id, m->ptr);
m->ptr += _pbcV_encode32(low, m->ptr);
break;
case PTYPE_FIXED64:
case PTYPE_SFIXED64:
id |= WT_BIT64;
m->ptr += _pbcV_encode32(id, m->ptr);
int64_encode(low,hi,m->ptr);
m->ptr += 8;
break;
case PTYPE_FIXED32:
case PTYPE_SFIXED32:
id |= WT_BIT32;
m->ptr += _pbcV_encode32(id, m->ptr);
int32_encode(low,m->ptr);
m->ptr += 4;
break;
case PTYPE_SINT32:
id |= WT_VARINT;
m->ptr += _pbcV_encode32(id, m->ptr);
m->ptr += _pbcV_zigzag32(low, m->ptr);
break;
case PTYPE_SINT64:
id |= WT_VARINT;
m->ptr += _pbcV_encode32(id, m->ptr);
m->ptr += _pbcV_zigzag((uint64_t)low | (uint64_t)hi << 32 , m->ptr);
break;
}
return 0;
}
int
pbc_wmessage_real(struct pbc_wmessage *m, const char *key, double v) {
struct _field * f = _pbcM_sp_query(m->type->name,key);
if (f == NULL) {
// todo : error
m->type->env->lasterror = "wmessage_real query key error";
return -1;
}
if (f->label == LABEL_PACKED) {
_packed_real(m , f, key , v);
return 0;
}
if (f->label == LABEL_OPTIONAL) {
if (v == f->default_v->real)
return 0;
}
int id = f->id << 3;
_expand(m,18);
switch (f->type) {
case PTYPE_FLOAT: {
id |= WT_BIT32;
m->ptr += _pbcV_encode32(id, m->ptr);
float_encode(v , m->ptr);
m->ptr += 4;
break;
}
case PTYPE_DOUBLE:
id |= WT_BIT64;
m->ptr += _pbcV_encode32(id, m->ptr);
double_encode(v , m->ptr);
m->ptr += 8;
break;
}
return 0;
}
int
pbc_wmessage_string(struct pbc_wmessage *m, const char *key, const char * v, int len) {
struct _field * f = _pbcM_sp_query(m->type->name,key);
if (f == NULL) {
// todo : error
m->type->env->lasterror = "wmessage_string query key error";
return -1;
}
bool varlen = false;
if (len <=0) {
varlen = true;
// -1 for add '\0'
len = strlen(v) - len;
}
if (f->label == LABEL_PACKED) {
if (f->type == PTYPE_ENUM) {
char temp[len+1];
if (!varlen || v[len] != '\0') {
memcpy(temp,v,len);
temp[len]='\0';
v = temp;
}
int enum_id = 0;
int err = _pbcM_si_query(f->type_name.e->name, v , &enum_id);
if (err) {
// todo : error , invalid enum
m->type->env->lasterror = "wmessage_string packed invalid enum";
return -1;
}
_packed_integer(m , f, key , enum_id , 0);
}
return 0;
}
if (f->label == LABEL_OPTIONAL) {
if (f->type == PTYPE_ENUM) {
if (strncmp(v , f->default_v->e.name, len) == 0 && f->default_v->e.name[len] =='\0') {
return 0;
}
} else if (f->type == PTYPE_STRING) {
if (len == f->default_v->s.len &&
strcmp(v, f->default_v->s.str) == 0) {
return 0;
}
}
}
int id = f->id << 3;
_expand(m,20);
switch (f->type) {
case PTYPE_ENUM : {
char temp[len+1];
if (!varlen || v[len] != '\0') {
memcpy(temp,v,len);
temp[len]='\0';
v = temp;
}
int enum_id = 0;
int err = _pbcM_si_query(f->type_name.e->name, v, &enum_id);
if (err) {
// todo : error , enum invalid
m->type->env->lasterror = "wmessage_string invalid enum";
return -1;
}
id |= WT_VARINT;
m->ptr += _pbcV_encode32(id, m->ptr);
m->ptr += _pbcV_encode32(enum_id, m->ptr);
break;
}
case PTYPE_STRING:
case PTYPE_BYTES:
id |= WT_LEND;
m->ptr += _pbcV_encode32(id, m->ptr);
m->ptr += _pbcV_encode32(len, m->ptr);
_expand(m,len);
memcpy(m->ptr , v , len);
m->ptr += len;
break;
}
return 0;
}
struct pbc_wmessage *
pbc_wmessage_message(struct pbc_wmessage *m, const char *key) {
struct _field * f = _pbcM_sp_query(m->type->name,key);
if (f == NULL) {
// todo : error
m->type->env->lasterror = "wmessage_message query key error";
return NULL;
}
pbc_var var;
var->p[0] = _wmessage_new(m->heap, f->type_name.m);
var->p[1] = f;
_pbcA_push(m->sub , var);
return var->p[0];
}
static void
_pack_packed_64(struct _packed *p,struct pbc_wmessage *m) {
int n = pbc_array_size(p->data);
int len = n * 8;
int i;
pbc_var var;
_expand(m,10 + len);
m->ptr += _pbcV_encode32(len, m->ptr);
switch (p->ptype) {
case PTYPE_DOUBLE:
for (i=0;i<n;i++) {
_pbcA_index(p->data, i, var);
double_encode(var->real , m->ptr + i * 8);
}
break;
default:
for (i=0;i<n;i++) {
_pbcA_index(p->data, i, var);
int64_encode(var->integer.low , var->integer.hi, m->ptr + i * 8);
}
break;
}
m->ptr += len;
}
static void
_pack_packed_32(struct _packed *p,struct pbc_wmessage *m) {
int n = pbc_array_size(p->data);
int len = n * 4;
int i;
pbc_var var;
_expand(m,10 + len);
m->ptr += _pbcV_encode32(len, m->ptr);
switch (p->ptype) {
case PTYPE_FLOAT:
for (i=0;i<n;i++) {
_pbcA_index(p->data, i, var);
float_encode(var->real , m->ptr + i * 8);
}
break;
default:
for (i=0;i<n;i++) {
_pbcA_index(p->data, i, var);
int32_encode(var->integer.low , m->ptr + i * 8);
}
break;
}
m->ptr += len;
}
static void
_pack_packed_varint(struct _packed *p,struct pbc_wmessage *m) {
int n = pbc_array_size(p->data);
int offset = m->ptr - m->buffer;
int len = n * 2;
if (p->ptype == PTYPE_BOOL) {
len = n;
}
int i;
pbc_var var;
_expand(m,10 + len);
int len_len = _pbcV_encode32(len, m->ptr);
m->ptr += len_len;
switch (p->ptype) {
case PTYPE_INT64:
case PTYPE_UINT64:
for (i=0;i<n;i++) {
_pbcA_index(p->data, i, var);
_expand(m,10);
m->ptr += _pbcV_encode((uint64_t)var->integer.low | (uint64_t)var->integer.hi << 32 , m->ptr);
}
break;
case PTYPE_INT32:
case PTYPE_BOOL:
case PTYPE_UINT32:
case PTYPE_ENUM:
for (i=0;i<n;i++) {
_pbcA_index(p->data, i, var);
_expand(m,10);
m->ptr += _pbcV_encode32(var->integer.low , m->ptr);
}
break;
case PTYPE_SINT32:
for (i=0;i<n;i++) {
_pbcA_index(p->data, i, var);
_expand(m,10);
m->ptr += _pbcV_zigzag32(var->integer.low, m->ptr);
}
break;
case PTYPE_SINT64:
for (i=0;i<n;i++) {
_pbcA_index(p->data, i, var);
_expand(m,10);
m->ptr += _pbcV_zigzag((uint64_t)var->integer.low | (uint64_t)var->integer.hi << 32 , m->ptr);
}
break;
default:
// error
memset(m->ptr , 0 , n);
m->ptr += n;
m->type->env->lasterror = "wmessage type error when pack packed";
break;
}
int end_offset = m->ptr - m->buffer;
int end_len = end_offset - (offset + len_len);
if (end_len != len) {
uint8_t temp[10];
int end_len_len = _pbcV_encode32(end_len, temp);
if (end_len_len != len_len) {
_expand(m, end_len_len);
memmove(m->buffer + offset + end_len_len ,
m->buffer + offset + len_len ,
end_len);
}
memcpy(m->buffer + offset , temp, end_len_len);
}
}
static void
_pack_packed(void *p, void *ud) {
struct _packed *packed = p;
struct pbc_wmessage * m = ud;
int id = packed->id << 3 | WT_LEND;
_expand(m,10);
m->ptr += _pbcV_encode32(id, m->ptr);
switch(packed->ptype) {
case PTYPE_DOUBLE:
case PTYPE_FIXED64:
case PTYPE_SFIXED64:
_pack_packed_64(packed,m);
break;
case PTYPE_FLOAT:
case PTYPE_FIXED32:
case PTYPE_SFIXED32:
_pack_packed_32(packed,m);
break;
default:
_pack_packed_varint(packed,m);
break;
}
}
void *
pbc_wmessage_buffer(struct pbc_wmessage *m, struct pbc_slice *slice) {
if (m->packed) {
_pbcM_sp_foreach_ud(m->packed , _pack_packed, m);
}
int i;
int n = pbc_array_size(m->sub);
for (i=0;i<n;i++) {
pbc_var var;
_pbcA_index(m->sub, i , var);
struct pbc_slice s;
pbc_wmessage_buffer(var->p[0] , &s);
if (s.buffer) {
struct _field * f = var->p[1];
int id = f->id << 3 | WT_LEND;
_expand(m,20+s.len);
m->ptr += _pbcV_encode32(id, m->ptr);
m->ptr += _pbcV_encode32(s.len, m->ptr);
memcpy(m->ptr, s.buffer, s.len);
m->ptr += s.len;
}
}
slice->buffer = m->buffer;
slice->len = m->ptr - m->buffer;
return m->buffer;
}

View File

@@ -1,592 +0,0 @@
local c = require "protobuf.c"
local setmetatable = setmetatable
local type = type
local table = table
local assert = assert
local pairs = pairs
local ipairs = ipairs
local string = string
local print = print
local io = io
local tinsert = table.insert
local rawget = rawget
module "protobuf"
local _pattern_cache = {}
local function clear_pat()
for _,v in pairs(_pattern_cache) do
c._pattern_delete(v.CObj)
end
end
local P = c._env_new()
setmetatable(_M , {
__gc = function(t)
clear_pat()
c._env_delete(P)
end })
function lasterror()
return c._last_error(P)
end
local decode_type_cache = {}
local _R_meta = {}
function _R_meta:__index(key)
local v = decode_type_cache[self._CType][key](self, key)
self[key] = v
return v
end
local function link_parent(self, parent)
local link = rawget(parent, _Children)
if link == nil then
link = {}
rawset(parent, "_Children" , link)
end
tinsert(link, self)
end
local function remove_cobj(self)
self._CObj = nil
setmetatable(self, nil)
local children = self._Children
if children then
for _,v in ipairs(children) do
remove_cobj(v)
end
end
end
local function delete_all(self)
c._rmessage_delete(self._CObj)
remove_cobj(self)
end
local _reader = {}
function _reader:int(key)
return c._rmessage_integer(self._CObj , key , 0)
end
function _reader:real(key)
return c._rmessage_real(self._CObj , key , 0)
end
function _reader:string(key)
return c._rmessage_string(self._CObj , key , 0)
end
function _reader:bool(key)
return c._rmessage_integer(self._CObj , key , 0) ~= 0
end
function _reader:message(key, message_type)
local rmessage = c._rmessage_message(self._CObj , key , 0)
if rmessage then
local v = {
_CObj = rmessage,
_CType = message_type,
_Parent = self,
}
return setmetatable( v , _R_meta )
end
end
function _reader:int32(key)
return c._rmessage_int32(self._CObj , key , 0)
end
function _reader:int64(key)
return c._rmessage_int64(self._CObj , key , 0)
end
function _reader:int52(key)
return c._rmessage_int52(self._CObj , key , 0)
end
function _reader:uint52(key)
return c._rmessage_uint52(self._CObj , key , 0)
end
function _reader:int_repeated(key)
local cobj = self._CObj
local n = c._rmessage_size(cobj , key)
local ret = {}
for i=0,n-1 do
tinsert(ret, c._rmessage_integer(cobj , key , i))
end
return ret
end
function _reader:real_repeated(key)
local cobj = self._CObj
local n = c._rmessage_size(cobj , key)
local ret = {}
for i=0,n-1 do
tinsert(ret, c._rmessage_real(cobj , key , i))
end
return ret
end
function _reader:string_repeated(key)
local cobj = self._CObj
local n = c._rmessage_size(cobj , key)
local ret = {}
for i=0,n-1 do
tinsert(ret, c._rmessage_string(cobj , key , i))
end
return ret
end
function _reader:bool_repeated(key)
local cobj = self._CObj
local n = c._rmessage_size(cobj , key)
local ret = {}
for i=0,n-1 do
tinsert(ret, c._rmessage_integer(cobj , key , i) ~= 0)
end
return ret
end
function _reader:message_repeated(key, message_type)
local cobj = self._CObj
local n = c._rmessage_size(cobj , key)
local ret = {}
for i=0,n-1 do
local m = {
_CObj = c._rmessage_message(cobj , key , i),
_CType = message_type,
_Parent = self,
}
tinsert(ret, setmetatable( m , _R_meta ))
end
return ret
end
function _reader:int32_repeated(key)
local cobj = self._CObj
local n = c._rmessage_size(cobj , key)
local ret = {}
for i=0,n-1 do
tinsert(ret, c._rmessage_int32(cobj , key , i))
end
return ret
end
function _reader:int64_repeated(key)
local cobj = self._CObj
local n = c._rmessage_size(cobj , key)
local ret = {}
for i=0,n-1 do
tinsert(ret, c._rmessage_int64(cobj , key , i))
end
return ret
end
function _reader:int52_repeated(key)
local cobj = self._CObj
local n = c._rmessage_size(cobj , key)
local ret = {}
for i=0,n-1 do
tinsert(ret, c._rmessage_int52(cobj , key , i))
end
return ret
end
function _reader:uint52_repeated(key)
local cobj = self._CObj
local n = c._rmessage_size(cobj , key)
local ret = {}
for i=0,n-1 do
tinsert(ret, c._rmessage_uint52(cobj , key , i))
end
return ret
end
_reader[1] = function(msg) return _reader.int end
_reader[2] = function(msg) return _reader.real end
_reader[3] = function(msg) return _reader.bool end
_reader[4] = function(msg) return _reader.string end
_reader[5] = function(msg) return _reader.string end
_reader[6] = function(msg)
local message = _reader.message
return function(self,key)
return message(self, key, msg)
end
end
_reader[7] = function(msg) return _reader.int64 end
_reader[8] = function(msg) return _reader.int32 end
_reader[9] = _reader[5]
_reader[10] = function(msg) return _reader.int52 end
_reader[11] = function(msg) return _reader.uint52 end
_reader[128+1] = function(msg) return _reader.int_repeated end
_reader[128+2] = function(msg) return _reader.real_repeated end
_reader[128+3] = function(msg) return _reader.bool_repeated end
_reader[128+4] = function(msg) return _reader.string_repeated end
_reader[128+5] = function(msg) return _reader.string_repeated end
_reader[128+6] = function(msg)
local message = _reader.message_repeated
return function(self,key)
return message(self, key, msg)
end
end
_reader[128+7] = function(msg) return _reader.int64_repeated end
_reader[128+8] = function(msg) return _reader.int32_repeated end
_reader[128+9] = _reader[128+5]
_reader[128+10] = function(msg) return _reader.int52_repeated end
_reader[128+11] = function(msg) return _reader.uint52_repeated end
local _decode_type_meta = {}
function _decode_type_meta:__index(key)
local t, msg = c._env_type(P, self._CType, key)
local func = assert(_reader[t],key)(msg)
self[key] = func
return func
end
setmetatable(decode_type_cache , {
__index = function(self, key)
local v = setmetatable({ _CType = key } , _decode_type_meta)
self[key] = v
return v
end
})
local _R_metagc = {
__index = _R_meta.__index
}
_R_metagc.__gc = assert(delete_all)
local function decode_message( message , buffer, length)
local rmessage = c._rmessage_new(P, message, buffer, length)
if rmessage then
local self = {
_CObj = rmessage,
_CType = message,
}
return setmetatable( self , _R_metagc )
end
end
--close_decoder = assert(delete_all)
function register( buffer)
c._env_register(P, buffer)
end
function register_file(filename)
local f = assert(io.open(filename , "rb"))
local buffer = f:read "*a"
c._env_register(P, buffer)
f:close()
end
----------- encode ----------------
local encode_type_cache = {}
local function encode_message(CObj, message_type, t)
local type = encode_type_cache[message_type]
for k,v in pairs(t) do
local func = type[k]
func(CObj, k , v)
end
end
local _writer = {
int = c._wmessage_integer,
real = c._wmessage_real,
enum = c._wmessage_string,
string = c._wmessage_string,
int64 = c._wmessage_int64,
int32 = c._wmessage_int32,
int52 = c._wmessage_int52,
uint52 = c._wmessage_uint52,
}
function _writer:bool(k,v)
c._wmessage_integer(self, k, v and 1 or 0)
end
function _writer:message(k, v , message_type)
local submessage = c._wmessage_message(self, k)
encode_message(submessage, message_type, v)
end
function _writer:int_repeated(k,v)
for _,v in ipairs(v) do
c._wmessage_integer(self,k,v)
end
end
function _writer:real_repeated(k,v)
for _,v in ipairs(v) do
c._wmessage_real(self,k,v)
end
end
function _writer:bool_repeated(k,v)
for _,v in ipairs(v) do
c._wmessage_integer(self, k, v and 1 or 0)
end
end
function _writer:string_repeated(k,v)
for _,v in ipairs(v) do
c._wmessage_string(self,k,v)
end
end
function _writer:message_repeated(k,v, message_type)
for _,v in ipairs(v) do
local submessage = c._wmessage_message(self, k)
encode_message(submessage, message_type, v)
end
end
function _writer:int32_repeated(k,v)
for _,v in ipairs(v) do
c._wmessage_int32(self,k,v)
end
end
function _writer:int64_repeated(k,v)
for _,v in ipairs(v) do
c._wmessage_int64(self,k,v)
end
end
function _writer:int52_repeated(k,v)
for _,v in ipairs(v) do
c._wmessage_int52(self,k,v)
end
end
function _writer:uint52_repeated(k,v)
for _,v in ipairs(v) do
c._wmessage_uint52(self,k,v)
end
end
_writer[1] = function(msg) return _writer.int end
_writer[2] = function(msg) return _writer.real end
_writer[3] = function(msg) return _writer.bool end
_writer[4] = function(msg) return _writer.string end
_writer[5] = function(msg) return _writer.string end
_writer[6] = function(msg)
local message = _writer.message
return function(self,key , v)
return message(self, key, v, msg)
end
end
_writer[7] = function(msg) return _writer.int64 end
_writer[8] = function(msg) return _writer.int32 end
_writer[9] = _writer[5]
_writer[10] = function(msg) return _writer.int52 end
_writer[11] = function(msg) return _writer.uint52 end
_writer[128+1] = function(msg) return _writer.int_repeated end
_writer[128+2] = function(msg) return _writer.real_repeated end
_writer[128+3] = function(msg) return _writer.bool_repeated end
_writer[128+4] = function(msg) return _writer.string_repeated end
_writer[128+5] = function(msg) return _writer.string_repeated end
_writer[128+6] = function(msg)
local message = _writer.message_repeated
return function(self,key, v)
return message(self, key, v, msg)
end
end
_writer[128+7] = function(msg) return _writer.int64_repeated end
_writer[128+8] = function(msg) return _writer.int32_repeated end
_writer[128+9] = _writer[128+5]
_writer[128+10] = function(msg) return _writer.int52_repeated end
_writer[128+11] = function(msg) return _writer.uint52_repeated end
local _encode_type_meta = {}
function _encode_type_meta:__index(key)
local t, msg = c._env_type(P, self._CType, key)
local func = assert(_writer[t],key)(msg)
self[key] = func
return func
end
setmetatable(encode_type_cache , {
__index = function(self, key)
local v = setmetatable({ _CType = key } , _encode_type_meta)
self[key] = v
return v
end
})
function encode( message, t , func)
local encoder = c._wmessage_new(P, message)
assert(encoder , message)
encode_message(encoder, message, t)
if func then
local buffer, len = c._wmessage_buffer(encoder)
func(buffer, len)
c._wmessage_delete(encoder)
else
local s = c._wmessage_buffer_string(encoder)
c._wmessage_delete(encoder)
return s
end
end
--------- unpack ----------
local _pattern_type = {
[1] = {"%d","i"},
[2] = {"%F","r"},
[3] = {"%d","b"},
[4] = {"%d","i"},
[5] = {"%s","s"},
[6] = {"%s","m"},
[7] = {"%D","x"},
[8] = {"%d","p"},
[10] = {"%D","d"},
[11] = {"%D","u"},
[128+1] = {"%a","I"},
[128+2] = {"%a","R"},
[128+3] = {"%a","B"},
[128+4] = {"%a","I"},
[128+5] = {"%a","S"},
[128+6] = {"%a","M"},
[128+7] = {"%a","X"},
[128+8] = {"%a","P"},
[128+10] = {"%a", "D" },
[128+11] = {"%a", "U" },
}
_pattern_type[9] = _pattern_type[5]
_pattern_type[128+9] = _pattern_type[128+5]
local function _pattern_create(pattern)
local iter = string.gmatch(pattern,"[^ ]+")
local message = iter()
local cpat = {}
local lua = {}
for v in iter do
local tidx = c._env_type(P, message, v)
local t = _pattern_type[tidx]
assert(t,tidx)
tinsert(cpat,v .. " " .. t[1])
tinsert(lua,t[2])
end
local cobj = c._pattern_new(P, message , "@" .. table.concat(cpat," "))
if cobj == nil then
return
end
local pat = {
CObj = cobj,
format = table.concat(lua),
size = 0
}
pat.size = c._pattern_size(pat.format)
return pat
end
setmetatable(_pattern_cache, {
__index = function(t, key)
local v = _pattern_create(key)
t[key] = v
return v
end
})
function unpack(pattern, buffer, length)
local pat = _pattern_cache[pattern]
return c._pattern_unpack(pat.CObj , pat.format, pat.size, buffer, length)
end
function pack(pattern, ...)
local pat = _pattern_cache[pattern]
return c._pattern_pack(pat.CObj, pat.format, pat.size , ...)
end
function check(typename , field)
if field == nil then
return c._env_type(P,typename)
else
return c._env_type(P,typename,field) ~=0
end
end
--------------
local default_cache = setmetatable({} , {__mode = "kv"})
local function default_table(typename)
local v = default_cache[typename]
if v then
return v
end
v = { __index = assert(decode_message(typename , "")) }
default_cache[typename] = v
return v
end
local decode_message_mt = {}
local function decode_message_cb(typename, buffer)
return setmetatable ( { typename, buffer } , decode_message_mt)
end
function decode(typename, buffer, length)
local ret = {}
local ok = c._decode(P, decode_message_cb , ret , typename, buffer, length)
if ok then
return setmetatable(ret , default_table(typename))
else
return false , c._last_error(P)
end
end
local function expand(tbl)
local typename = rawget(tbl , 1)
local buffer = rawget(tbl , 2)
tbl[1] , tbl[2] = nil , nil
assert(c._decode(P, decode_message_cb , tbl , typename, buffer), typename)
setmetatable(tbl , default_table(typename))
end
function decode_message_mt.__index(tbl, key)
expand(tbl)
return tbl[key]
end
function decode_message_mt.__pairs(tbl)
expand(tbl)
return pairs(tbl)
end
local function set_default(typename, tbl)
for k,v in pairs(tbl) do
if type(v) == "table" then
local t, msg = c._env_type(P, typename, k)
if t == 6 then
set_default(msg, v)
elseif t == 128+6 then
for _,v in ipairs(v) do
set_default(msg, v)
end
end
end
end
return setmetatable(tbl , default_table(typename))
end
default=set_default

View File

@@ -1,397 +0,0 @@
-----------------------
-- simple proto parser
-----------------------
local lpeg = require "lpeg"
local P = lpeg.P
local S = lpeg.S
local R = lpeg.R
local C = lpeg.C
local Ct = lpeg.Ct
local Cg = lpeg.Cg
local Cc = lpeg.Cc
local V = lpeg.V
local next = next
local error = error
local tonumber = tonumber
local pairs = pairs
local ipairs = ipairs
local rawset = rawset
local tinsert = table.insert
local smatch = string.match
local sbyte = string.byte
local internal_type = {
double = "TYPE_DOUBLE",
float = "TYPE_FLOAT",
uint64 = "TYPE_UINT64",
int = "TYPE_INT32",
int32 = "TYPE_INT32",
int64 = "TYPE_INT64",
fixed64 = "TYPE_FIXED64",
fixed32 = "TYPE_FIXED32",
bool = "TYPE_BOOL",
string = "TYPE_STRING",
bytes = "TYPE_BYTES",
uint32 = "TYPE_UINT32",
sfixed32 = "TYPE_SFIXED32",
sfixed64 = "TYPE_SFIXED64",
sint32 = "TYPE_SINT32",
sint64 = "TYPE_SINT64",
}
local function count_lines(_,pos, parser_state)
if parser_state.pos < pos then
parser_state.line = parser_state.line + 1
parser_state.pos = pos
end
return pos
end
local exception = lpeg.Cmt( lpeg.Carg(1) , function ( _ , pos, parser_state)
error( "syntax error at [" .. (parser_state.file or "") .."] (" .. parser_state.line ..")" )
return pos
end)
local eof = P(-1)
local newline = lpeg.Cmt((P"\n" + "\r\n") * lpeg.Carg(1) ,count_lines)
local line_comment = "//" * (1 - newline) ^0 * (newline + eof)
local blank = S" \t" + newline + line_comment
local blank0 = blank ^ 0
local blanks = blank ^ 1
local alpha = R"az" + R"AZ" + "_"
local alnum = alpha + R"09"
local str_c = (1 - S("\\\"")) + P("\\") * 1
local str = P"\"" * C(str_c^0) * "\""
local dotname = ("." * alpha * alnum ^ 0) ^ 0
local typename = C(alpha * alnum ^ 0 * dotname)
local name = C(alpha * alnum ^ 0)
local filename = C((alnum + "/" + "." + "-")^1)
local id = R"09" ^ 1 / tonumber + "max" * Cc(-1)
local bool = "true" * Cc(true) + "false" * Cc(false)
local value = str + bool + name + id
local patterns = {}
local enum_item = Cg(name * blank0 * "=" * blank0 * id * blank0 * ";" * blank0)
local function insert(tbl, k,v)
tinsert(tbl, { name = k , number = v })
return tbl
end
patterns.ENUM = Ct(Cg("enum","type") * blanks * Cg(typename,"name") * blank0 *
"{" * blank0 *
Cg(lpeg.Cf(Ct"" * enum_item^1 , insert),"value")
* "}" * blank0)
local prefix_field = P"required" * Cc"LABEL_REQUIRED" +
P"optional" * Cc"LABEL_OPTIONAL" +
P"repeated" * Cc"LABEL_REPEATED"
local postfix_pair = blank0 * Cg(name * blank0 * "=" * blank0 * value * blank0)
local postfix_pair_2 = blank0 * "," * postfix_pair
local postfix_field = "[" * postfix_pair * postfix_pair_2^0 * blank0 * "]"
local options = lpeg.Cf(Ct"" * postfix_field , rawset) ^ -1
local function setoption(t, options)
if next(options) then
t.options = options
end
return t
end
local message_field = lpeg.Cf (
Ct( Cg(prefix_field,"label") * blanks *
Cg(typename,"type_name") * blanks *
Cg(name,"name") * blank0 * "=" * blank0 *
Cg(id,"number")
) * blank0 * options ,
setoption) * blank0 * ";" * blank0
local extensions = Ct(
Cg("extensions" , "type") * blanks *
Cg(id,"start") * blanks * "to" * blanks *
Cg(id,"end") * blank0 * ";" * blank0
)
patterns.EXTEND = Ct(
Cg("extend", "type") * blanks *
Cg(typename, "name") * blank0 * "{" * blank0 *
Cg(Ct((message_field) ^ 1),"extension") * "}" * blank0
)
patterns.MESSAGE = P { Ct(
Cg("message","type") * blanks *
Cg(typename,"name") * blank0 * "{" * blank0 *
Cg(Ct((message_field + patterns.ENUM + extensions + patterns.EXTEND + V(1)) ^ 1),"items") * "}" * blank0
) }
patterns.OPTION = Ct(
Cg("option" , "type") * blanks *
Cg(name, "name") * blank0 * "=" * blank0 *
Cg(value, "value")
) * blank0 * ";" * blank0
patterns.IMPORT = Ct( Cg("import" , "type") * blanks * Cg(filename, "name") ) * blank0
patterns.PACKAGE = Ct( Cg("package", "type") * blanks * Cg(typename, "name") ) * blank0 * ";" * blank0
local proto_tbl = { "PROTO" }
do
local k, v = next(patterns)
local p = V(k)
proto_tbl[k] = v
for k,v in next , patterns , k do
proto_tbl[k] = v
p = p + V(k)
end
proto_tbl.PROTO = Ct(blank0 * p ^ 1)
end
local proto = P(proto_tbl)
local deal = {}
function deal:import(v)
self.dependency = self.dependency or {}
tinsert(self.dependency , v.name)
end
function deal:package(v)
self.package = v.name
end
function deal:enum(v)
self.enum_type = self.enum_type or {}
tinsert(self.enum_type , v)
end
function deal:option(v)
self.options = self.options or {}
self.options[v.name] = v.value
end
function deal:extend(v)
self.extension = self.extension or {}
local extendee = v.name
for _,v in ipairs(v.extension) do
v.extendee = extendee
v.type = internal_type[v.type_name]
if v.type then
v.type_name = nil
end
tinsert(self.extension , v)
end
end
function deal:extensions(v)
self.extension_range = self.extension_range or {}
tinsert(self.extension_range, v)
end
local function _add_nested_message(self, item)
if item.type == nil then
item.type = internal_type[item.type_name]
if item.type then
item.type_name = nil
end
self.field = self.field or {}
tinsert(self.field, item)
else
local f = deal[item.type]
item.type = nil
f(self , item)
end
end
function deal:message(v)
self.nested_type = self.nested_type or {}
local m = { name = v.name }
tinsert(self.nested_type , m)
for _,v in ipairs(v.items) do
_add_nested_message(m, v)
end
end
local function fix(r)
local p = {}
for _,v in ipairs(r) do
local f = deal[v.type]
v.type = nil
f(p , v)
end
p.message_type = p.nested_type
p.nested_type = nil
return p
end
--- fix message name
local NULL = {}
local function _match_name(namespace , n , all)
if sbyte(n) == 46 then
return n
end
repeat
local name = namespace .. "." .. n
if all[name] then
return name
end
namespace = smatch(namespace,"(.*)%.[%w_]+$")
until namespace == nil
end
local function _fix_field(namespace , field, all)
local type_name = field.type_name
if type_name == "" then
field.type_name = nil
return
elseif type_name == nil then
return
end
local full_name = assert(_match_name(namespace, field.type_name, all) , field.type_name , all)
field.type_name = full_name
field.type = all[full_name]
local options = field.options
if options then
if options.default then
field.default_value = tostring(options.default)
options.default = nil
end
if next(options) == nil then
field.options = nil
end
end
end
local function _fix_extension(namespace, ext, all)
for _,field in ipairs(ext or NULL) do
field.extendee = assert(_match_name(namespace, field.extendee,all),field.extendee)
_fix_field(namespace , field , all)
end
end
local function _fix_message(msg , all)
for _,field in ipairs(msg.field or NULL) do
_fix_field(assert(all[msg],msg.name) , field , all)
end
for _,nest in ipairs(msg.nested_type or NULL) do
_fix_message(nest , all)
end
_fix_extension(all[msg] , msg.extension , all)
end
local function _fix_typename(file , all)
for _,message in ipairs(file.message_type or NULL) do
_fix_message(message , all)
end
_fix_extension(file.package , file.extension , all)
end
--- merge messages
local function _enum_fullname(prefix, enum , all)
local fullname
if sbyte(enum.name) == 46 then
fullname = enum.name
else
fullname = prefix .. "." .. enum.name
end
all[fullname] = "TYPE_ENUM"
all[enum] = fullname
end
local function _message_fullname(prefix , msg , all)
local fullname
if sbyte(msg.name) == 46 then
fullname = msg.name
else
fullname = prefix .. "." .. msg.name
end
all[fullname] = "TYPE_MESSAGE"
all[msg] = fullname
for _,nest in ipairs(msg.nested_type or NULL) do
_message_fullname(fullname , nest , all)
end
for _,enum in ipairs(msg.enum_type or NULL) do
_enum_fullname(fullname , enum , all)
end
end
local function _gen_fullname(file , all)
local prefix = ""
if file.package then
prefix = "." .. file.package
end
for _,message in ipairs(file.message_type or NULL) do
_message_fullname(prefix , message , all)
end
for _,enum in ipairs(file.enum_type or NULL) do
_enum_fullname(prefix , enum , all)
end
end
--- parser
local parser = {}
local function parser_one(text,filename)
local state = { file = filename, pos = 0, line = 1 }
local r = lpeg.match(proto * -1 + exception , text , 1, state )
local t = fix(r)
return t
end
function parser.parser(text,filename)
local t = parser_one(text,filename)
local all = {}
_gen_fullname(t,all)
_fix_typename(t , all)
return t
end
local pb = require "protobuf"
function parser.register(fileset , path)
local all = {}
local files = {}
if type(fileset) == "string" then
fileset = { fileset }
end
for _, filename in ipairs(fileset) do
local fullname
if path then
fullname = path .. "/" .. filename
else
fullname = filename
end
local f = assert(io.open(fullname , "r"))
local buffer = f:read "*a"
f:close()
local t = parser_one(buffer,filename)
_gen_fullname(t,all)
t.name = filename
tinsert(files , t)
end
for _,file in ipairs(files) do
_fix_typename(file,all)
end
local pbencode = pb.encode("google.protobuf.FileDescriptorSet" , { file = files })
if pbencode == nil then
error(pb.lasterror())
end
pb.register(pbencode)
return files
end
return parser