mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-22 02:53:09 +00:00
remove lpeg & pbc
This commit is contained in:
23
Makefile
23
Makefile
@@ -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 $@
|
||||
|
||||
|
||||
77
lpeg/HISTORY
77
lpeg/HISTORY
@@ -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 |
2405
lpeg/lpeg.c
2405
lpeg/lpeg.c
File diff suppressed because it is too large
Load Diff
38
lpeg/lpeg.h
38
lpeg/lpeg.h
@@ -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
|
||||
1423
lpeg/lpeg.html
1423
lpeg/lpeg.html
File diff suppressed because it is too large
Load Diff
BIN
lpeg/lpeg.o
BIN
lpeg/lpeg.o
Binary file not shown.
@@ -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
|
||||
|
||||
486
lpeg/re.html
486
lpeg/re.html
@@ -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><name></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 -> 'string'</code></td> <td>string capture</td></tr>
|
||||
<tr><td><code>p -> "string"</code></td> <td>string capture</td></tr>
|
||||
<tr><td><code>p -> {}</code></td> <td>table capture</td></tr>
|
||||
<tr><td><code>p -> name</code></td> <td>function/query/string capture
|
||||
equivalent to <code>p / defs[name]</code></td></tr>
|
||||
<tr><td><code>p => 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 <- 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]+")) --> 12
|
||||
|
||||
-- similar, but also captures (and returns) the number
|
||||
print(re.find("the number 423 is odd", "{[0-9]+}")) --> 12 423
|
||||
|
||||
-- returns all words in a string
|
||||
print(re.match("the number 423 is odd", "({%a+} / .)*"))
|
||||
--> 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 <- "(" ([^()] / balanced)* ")" ]]
|
||||
</pre>
|
||||
|
||||
<h3>String reversal</h3>
|
||||
<p>
|
||||
The next example reverses a string:
|
||||
</p>
|
||||
<pre class="example">
|
||||
rev = re.compile[[ R <- (!.) -> '' / ({.} R) -> '%2%1']]
|
||||
print(rev:match"0123456789") --> 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 <- ( field (',' field)* ) -> {} (%nl / !.)
|
||||
field <- escaped / nonescaped
|
||||
nonescaped <- { [^,"%nl]* }
|
||||
escaped <- '"' {~ ([^"] / '""' -> '"')* ~} '"'
|
||||
]]
|
||||
</pre>
|
||||
|
||||
<h3>Lua's long strings</h3>
|
||||
<p>
|
||||
The next example matches Lua long strings:
|
||||
</p>
|
||||
<pre class="example">
|
||||
c = re.compile([[
|
||||
longstring <- ('[' {:eq: '='* :} '[' close) -> void
|
||||
close <- ']' =eq ']' / . close
|
||||
]], {void = function () end})
|
||||
|
||||
print(c:match'[==[]]===]]]]==]===[]') --> 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 <- (name s)*
|
||||
name <- [a-z][a-z]*
|
||||
s <- %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 <- (name s)* -> {}
|
||||
name <- {[a-z][a-z]*} -> {}
|
||||
s <- %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 <- ({:ident:' '*:} line
|
||||
((=ident !' ' line) / &(=ident ' ') block)*) -> {}
|
||||
line <- {[^%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 <- {~ item* ~}
|
||||
item <- macro / [^()] / '(' item* ')'
|
||||
arg <- ' '* {~ (!',' item)* ~}
|
||||
args <- '(' arg (',' arg)* ')'
|
||||
-- now we define some macros
|
||||
macro <- ('apply' args) -> '%1(%2)'
|
||||
/ ('add' args) -> '%1 + %2'
|
||||
/ ('mul' args) -> '%1 * %2'
|
||||
]]
|
||||
|
||||
print(p:match"add(mul(a,b), apply(f,x))") --> 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 <- exp !.
|
||||
exp <- S (alternative / grammar)
|
||||
|
||||
alternative <- seq ('/' S seq)*
|
||||
seq <- prefix*
|
||||
prefix <- '&' S prefix / '!' S prefix / suffix
|
||||
suffix <- primary S (([+*?]
|
||||
/ '^' [+-]? num
|
||||
/ '->' S (string / '{}' / name)
|
||||
/ '=>' S name) S)*
|
||||
|
||||
primary <- '(' exp ')' / string / class / defined
|
||||
/ '{:' (name ':')? exp ':}'
|
||||
/ '=' name
|
||||
/ '{}'
|
||||
/ '{~' exp '~}'
|
||||
/ '{' exp '}'
|
||||
/ '.'
|
||||
/ name S !arrow
|
||||
/ '<' name '>' -- old-style non terminals
|
||||
|
||||
grammar <- definition+
|
||||
definition <- name S arrow exp
|
||||
|
||||
class <- '[' '^'? item (!']' item)* ']'
|
||||
item <- defined / range / .
|
||||
range <- . '-' [^]]
|
||||
|
||||
S <- (%s / '--' [^%nl]*)* -- spaces and comments
|
||||
name <- [A-Za-z][A-Za-z0-9_]*
|
||||
arrow <- '<-'
|
||||
num <- [0-9]+
|
||||
string <- '"' [^"]* '"' / "'" [^']* "'"
|
||||
defined <- '%' name
|
||||
|
||||
]=]
|
||||
|
||||
print(re.match(p, p)) -- a self description must match itself
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
<h2><a name="license">License</a></h2>
|
||||
|
||||
<p>
|
||||
Copyright © 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>
|
||||
248
lpeg/re.lua
248
lpeg/re.lua
@@ -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
|
||||
1188
lpeg/test.lua
1188
lpeg/test.lua
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -1,2 +0,0 @@
|
||||
See https://github.com/cloudwu/pbc
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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))
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user