mirror of
https://github.com/google/pebble.git
synced 2025-08-24 20:17:26 -04:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
116
third_party/nanopb/AUTHORS.txt
vendored
Normal file
116
third_party/nanopb/AUTHORS.txt
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
Petteri Aimonen <jpa@npb.mail.kapsi.fi>
|
||||
Michael Poole <mdpoole@troilus.org>
|
||||
Daniel Kan <extremeblue99@gmail.com>
|
||||
Stan Hu <stanhu@aclimalabs.com>
|
||||
David Hotham <david.hotham@blueyonder.co.uk>
|
||||
Steffen Siering <steffen siering gmail com>
|
||||
Jens Steinhauser <jens.steinhauser@gmail.com>
|
||||
Pavel Ilin <ilin.pa@gmail.com>
|
||||
Kent Ryhorchuk <kryhorchuk@xeralux.com>
|
||||
Martin Donath <scifish@gmail.com>
|
||||
Oliver Lee <oliverzlee@gmail.com>
|
||||
Michael Haberler <git@mah.priv.at>
|
||||
Nicolas Colomer <ncolomer@viadeoteam.com>
|
||||
Ivan Kravets <me@ikravets.com>
|
||||
Kyle Manna <kyle@kylemanna.com>
|
||||
Benjamin Kamath <ben.kamath@synapse.com>
|
||||
Andrew Ruder <andrew.ruder@elecsyscorp.com>
|
||||
Kenshi Kawaguchi <kenshi@recurse.ca>
|
||||
isotes <isotes@gmail.com>
|
||||
Maxim Khitrov <max@mxcrypt.com>
|
||||
Yaniv Mordekhay <yanivmo@users.noreply.github.com>
|
||||
Ming Zhao <mzhao@luminatewireless.com>
|
||||
Google, Inc.
|
||||
Tom Roeder <tmroeder@google.com>
|
||||
Piotr Sikora <piotrsikora@google.com>
|
||||
Bernhard Krämer <bdkrae@gmail.com>
|
||||
Konstantin Podsvirov <konstantin@podsvirov.pro>
|
||||
William A. Kennington III <wak@google.com>
|
||||
Guillaume Lager <g.lager@innoseis.com>
|
||||
Tobias Haegermarck <tobias.haegermarck@gmail.com>
|
||||
Justin DeMartino <jdemarti@gmail.com>
|
||||
Constantine Grantcharov <cgrantcharov@trustpointinnovation.com>
|
||||
Nick Ewalt <nicholasewalt@google.com>
|
||||
Harald Fernengel <harryf@gmx.com>
|
||||
Alice Wang <aw@squareup.com>
|
||||
Kevin Fitch <kfitch42@gmail.com>
|
||||
Kamal Marhubi <kamal@marhubi.com>
|
||||
Elco Jacobs <elco@brewpi.com>
|
||||
Sébastien Morin <sebastien.morin@primerogames.com>
|
||||
Dave Flogeras <dflogeras2@gmail.com>
|
||||
Edward Z. Yang <ezyang@mit.edu>
|
||||
Robbie Shade <rjshade@google.com>
|
||||
Andrew Ballinger <andrewballinger@stratisopt.com>
|
||||
Hamina, Juha-Pekka <Juha-Pekka.Hamina@nordicsemi.no>
|
||||
Jason Bishop <jason.bishop@bigassfans.com>
|
||||
matejcik <ja@matejcik.cz>
|
||||
Tobias Müller <Tobias_Mueller@twam.info>
|
||||
Jari Vetoniemi <mailroxas@gmail.com>
|
||||
Gabriel Staples <ercaguy@gmail.com>
|
||||
Amarnath <amarnath.h.96@gmail.com>
|
||||
Michal Rostecki <mrostecki@suse.de>
|
||||
Pei Wang <wangpei10@baidu.com>
|
||||
Noah Pendleton <2538614+noahp@users.noreply.github.com>
|
||||
Pavol Rusnak <pavol@rusnak.io>
|
||||
der-imp <falkjan@msn.com>
|
||||
Mark Hill <markleehill@gmail.com>
|
||||
Torfinn Berset <torfinn@bloom-life.com>
|
||||
Bo Langgaard Lind <bo.langgaard.lind@gmail.com>
|
||||
Stephane Dorre <stephane.dorre@cobi.bike>
|
||||
Phillip Cao <Phillip.Cao@fphcare.co.nz>
|
||||
Melvin Wang <melvin.mc.wang@gmail.com>
|
||||
Joshua Salzedo <thHunkn0WNd@gmail.com>
|
||||
Adam Klama <klama.adam@gmail.com>
|
||||
Anton Matosov <amatosov@roblox.com>
|
||||
berni155 <bdkrae@gmail.com>
|
||||
bolind <bolind@users.noreply.github.com>
|
||||
David Lin <dtwlin@google.com>
|
||||
dch <david.hotham@blueyonder.co.uk>
|
||||
devjoa <devjoa@gmail.com>
|
||||
Evan Fisher <schleb@gmail.com>
|
||||
Fay <fay2003hiend@gmail.com>
|
||||
Florian Märkl <info@florianmaerkl.de>
|
||||
Franck <franck.sehedic@ledger.fr>
|
||||
Ilya Averyanov <i.averyanov@geoscan.aero>
|
||||
John Ullman <jrullman@google.com>
|
||||
Ket3r <peter.kempter@gmail.com>
|
||||
maciej <maciej.matuszak@gmail.com>
|
||||
Marek Zukal <marek.zukal@gmail.com>
|
||||
Paul Beusterien <paulbeusterien@google.com>
|
||||
Rogers Guedes <rogers.guedes@smdautomacao.com>
|
||||
Stefan R. Filipek <srfilipek@gmail.com>
|
||||
T. Carl Beery <beeryt@users.noreply.github.com>
|
||||
Vitali Lovich <vlovich@google.com>
|
||||
Vojtěch Boček <vbocek@gmail.com>
|
||||
Wael Nasreddine <wael.nasreddine@gmail.com>
|
||||
wangli28 <wangli28@beyondsoft.com>
|
||||
Zukaitis <gediminas.zukaitis@office.auriga.msk>
|
||||
Alex Pacini <alexpacini90@gmail.com>
|
||||
Cong <congusbongus@gmail.com>
|
||||
kurddt <kurddt@users.noreply.github.com>
|
||||
otopetrik <oto.petrik@gmail.com>
|
||||
Psy-Kai <psykai1993@googlemail.com>
|
||||
a1lu <a1lu@users.noreply.github.com>
|
||||
L <46594312+WakandaO2@users.noreply.github.com>
|
||||
Melvin Wang <mwang@sibros.tech>
|
||||
Tim Gates <tim.gates@iress.com>
|
||||
leabut <leabut@users.noreply.github.com>
|
||||
Angel ILIEV <a.v.iliev13@gmail.com>
|
||||
Jakub Tymejczyk <jakub@tymejczyk.pl>
|
||||
Matthew Simmons <simmonmt@acm.org>
|
||||
Anthony Pesch <inolen@gmail.com>
|
||||
Avik De <avikde@gmail.com>
|
||||
ConradWood <github@conradwood.net>
|
||||
David Sabatie <david.sabatie@notrenet.com>
|
||||
Sebastian Stockhammer <sebastian.stockhammer@rosenberger.de>
|
||||
Gil Shapira <gil.shapira@intusurg.com>
|
||||
Ian Frosst <ianjfrosst@gmail.com>
|
||||
Ingo Kresse <ingo.kresse@kuka.com>
|
||||
Ivan Zrno <ivan.zrno2@gmail.com>
|
||||
Jonathan Seilkopf <j.seilkopf@isatech.de>
|
||||
Karl Ljungkvist <k.ljungkvist@gmail.com>
|
||||
Mathis Logemann <mathisloge@gmail.com>
|
||||
Oleg Dolgy <60554929+odolgy@users.noreply.github.com>
|
||||
Pavel Sokolov <pavel@sokolov.me>
|
||||
Slavey Karadzhov <slav@attachix.com>
|
||||
Tobias Nießen <tniessen@tnie.de>
|
21
third_party/nanopb/BUILD.bazel
vendored
Normal file
21
third_party/nanopb/BUILD.bazel
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
licenses(["notice"])
|
||||
|
||||
exports_files(["LICENSE.txt"])
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
cc_library(
|
||||
name = "nanopb",
|
||||
srcs = [
|
||||
"pb_common.c",
|
||||
"pb_decode.c",
|
||||
"pb_encode.c",
|
||||
],
|
||||
hdrs = [
|
||||
"pb.h",
|
||||
"pb_common.h",
|
||||
"pb_decode.h",
|
||||
"pb_encode.h",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
563
third_party/nanopb/CHANGELOG.txt
vendored
Normal file
563
third_party/nanopb/CHANGELOG.txt
vendored
Normal file
|
@ -0,0 +1,563 @@
|
|||
nanopb-0.4.6 (2022-05-30)
|
||||
Fix passing of error message from substream callback (#703)
|
||||
Fix comments going to wrong member variables (#701)
|
||||
Fix regression in 0.4.3 where generator did not find all dependencies (#720)
|
||||
Fix FindNanopb.cmake not finding options file (#659)
|
||||
Fix double-definition errors with size_union (#692)
|
||||
Fix generator error with same inner message name (#746)
|
||||
Fix infinite recursion in generator/protoc script (#762)
|
||||
Fix unicode comment handling for Python 2 (#740)
|
||||
Fix compiler warnings with PB_BUFFER_ONLY (#717)
|
||||
Fix options dependency in nanopb.mk (#666)
|
||||
Fix handling of filenames with dot in them in FindNanopb.cmake (#756)
|
||||
Add fallback_type option (#772, #773)
|
||||
Use C11 static assert mechanism by default (#761, #766)
|
||||
Use 'static_assert' keyword for iar (#679)
|
||||
Explicitly check for pItem == NULL to satisfy Xcode analyzer (#667, #674)
|
||||
Support --proto-path as alias to -I (#749)
|
||||
Refactor name mangling to separate class, improve error messages (#735)
|
||||
Move PB_WT_PACKED definition to the header to fix compiler warnings (#671)
|
||||
FindNanopb.cmake: use --nanopb_opt for option passing by default (#752)
|
||||
FindNanopb.cmake: Add option NANOPB_GENERATE_CPP_STANDALONE (#741)
|
||||
FindNanopb.cmake: Add PROTOC_OPTIONS variable (#768, #771)
|
||||
CMakeLists: add build interface for using as a submodule (#669)
|
||||
CMakeLists: fix error with nanopb_BUILD_GENERATOR=OFF (#764)
|
||||
CMakeLists: make more uniform (#676)
|
||||
CMakeLists: Fix uninitialized PYTHON_INSTDIR (#652)
|
||||
Clean up CMake examples (#741)
|
||||
Rebuild nanopb_pb2.py and print version numbers on import failure (#733, #742)
|
||||
Use memcpy instead of iterating on buf_read/write (#751)
|
||||
Add generator support for PlatformIO (#718)
|
||||
Add clean target to generator/proto/Makefile (#681)
|
||||
Windows .bats: use standard python invocation instead of py.exe launcher (#657)
|
||||
Fix problems running tests with newer SCons version
|
||||
Improve handling of varint overflows
|
||||
Improve optimization for little-endian platforms
|
||||
|
||||
NOTE: During development, prereleases were published on platform.io registry
|
||||
as versions 0.4.6 - 0.4.6.3. The version 0.4.6.4 on platform.io corresponds
|
||||
to the real final 0.4.6 release.
|
||||
|
||||
|
||||
nanopb-0.4.5 (2021-03-22)
|
||||
Fix invalid free() with oneof (#647, GHSA-7mv5-5mxh-qg88)
|
||||
Fix unordered field numbers inside oneof causing fields to be ignored (#617)
|
||||
Fix pb_decode() not initializing fields inside oneof (#635
|
||||
Fix compiler errors with complex oneof hierarchy and sizeof() (#610)
|
||||
Fix descriptor width calculation for 64-bit types (#644)
|
||||
Fix compiler error in generated initializer for submessage callback (#631)
|
||||
Fix duplicate union definition in generated file (#637)
|
||||
Fix test case build error on SCons 4.1.0
|
||||
Pip package: include nanopb_pb2.py (#629)
|
||||
Make generator consider dependencies recursively (#610)
|
||||
Bazel build system updates (#633)
|
||||
Add support for including comments from .proto file (#85, #645)
|
||||
|
||||
nanopb-0.4.4 (2020-11-25)
|
||||
Fix memory leak with oneofs and PB_ENABLE_MALLOC (#615, GHSA-85rr-4rh9-hhwh)
|
||||
Fix generator error when oneof contains a single unresolved field size (#610)
|
||||
Fix unsigned enums not working correctly inside OneOf (#611)
|
||||
Fix recursion depth exceeded error in generator (#493)
|
||||
Add '--version' option to nanopb_generator.py (#607)
|
||||
Add support for proto3 optional fields introduced in protoc 3.12 (#591)
|
||||
Add better error message when enum type is not found (#592)
|
||||
Allow specifying descriptorsize on field level also (#546)
|
||||
Allow multiple targets to be created by calling NANOPB_GENERATE_CPP() (#596)
|
||||
Conanfile: Add protobuf-nanopb library to cpp_info.libs (#605)
|
||||
Include version number in generator verbose output
|
||||
Convert documentation to markdown format (#587)
|
||||
Remove outdated transitional generator/nanopb/options.proto.
|
||||
Test case improvements
|
||||
Documentation improvements
|
||||
|
||||
nanopb-0.4.3 (2020-09-21)
|
||||
Fix generator error when output is in current directory (#553)
|
||||
Fix issue with unknown message sizes being referred inside oneof encoded size calculation (#569)
|
||||
Fix problem with [default=xxxx, (nanopb).proto3=true] field option combination (#558)
|
||||
Fix cross compilation with Conan build system (#568)
|
||||
Better support C++ types in generated structs (#577)
|
||||
CMake rule improvements (#554, #555, #556, #561, #564)
|
||||
Generator: fix compatibility bug with Python 3.1 and earlier
|
||||
Make Linux and Mac packages use grpcio protoc
|
||||
Make pb_decode_varint32() reject overlong varint encodings.
|
||||
Performance optimizations
|
||||
Test case improvements
|
||||
Documentation improvements
|
||||
|
||||
NOTE: version 0.4.3 changes layout of pb_msgdesc_t. It requires recompiling .pb.c files and
|
||||
thus breaks ABI compatibility. In general, ABI compatibility is not currently maintained
|
||||
between any nanopb versions.
|
||||
|
||||
NOTE: There was an apparent false positive virus identification by Windows Defender of the
|
||||
PyInstaller 3.6 based Windows package nanopb-0.4.3-windows-x86.zip. The package was replaced
|
||||
by nanopb-0.4.3-p1-windows-x86.zip with rebuilt PyInstaller 4.0, which seems to avoid the problem.
|
||||
Actual nanopb code is unchanged between the packages.
|
||||
|
||||
nanopb-0.4.2 (2020-06-23)
|
||||
Fix buffer overflow when encoding bytes with size set to 65535 (#547, GHSA-3p39-mfxg-hrq4)
|
||||
Fix segfault with pointer fields and proto3_singular_msgs = true. (#504,#505)
|
||||
Fix Windows 10 temp file handling (#486)
|
||||
Fix macro name conflicts (ATMEGA32U4 UENUM and more) (#522)
|
||||
Fix generator error with nested messages and default values (#487)
|
||||
Fix nanopb_generator exception on enums with aliases (#535)
|
||||
Fix compile error when struct members are called X or a (#492)
|
||||
Fix sizeof(union ...) fallback not compiling with C++ (#415, #494)
|
||||
Fix "missing required field" error with submessage callback (#544)
|
||||
Fix field descriptor sizing with submsg_callback option (#545)
|
||||
Fix protoc calling on Python 2 (#503)
|
||||
Fix handling of varying NaN representations in PB_CONVERT_DOUBLE_FLOAT (#543)
|
||||
Fix clang undefined behavior sanitizer errors.
|
||||
Change generator to use Python 3 by default (#441, #509)
|
||||
Binary packages updated to use Python 3 and grpcio-tools
|
||||
Add support for infinity and nan floating-point defaults (#530, #538)
|
||||
Add generator option sort_by_tag (#542)
|
||||
Add type_override option to override type defined in .proto (#497)
|
||||
Set proto2 enum fields to first value when no default is given, even if nonzero (#532,#539)
|
||||
Include protoc-gen-nanopb in path in protoc wrapper script
|
||||
Properly pass error status from protoc wrapper when calling binary protoc
|
||||
Generator: pass --include_imports when calling protoc (#494)
|
||||
Create intermediate directories when writing files to relative path (#512)
|
||||
Add current directory to include path for protoc (#499)
|
||||
Update readme to use nanopb_generator.py directly
|
||||
Regression test for proto3 incorrectly considered empty (#504)
|
||||
CMake: change package name to Nanopb for cmake 3.17 compatibility (#506)
|
||||
CMake: remove find_package(PythonInterp) (#508)
|
||||
CMake: use split --nanopb_opt only on protoc >= 3.6 (#515)
|
||||
CMake: Relax python version spec, allowing Python3. (#534)
|
||||
Swift package manager (#549)
|
||||
Rename BUILD as BUILD.bazel (#537)
|
||||
|
||||
Note: Windows binary packages in 0.4.2 and later require Windows 7 or newer.
|
||||
|
||||
nanopb-0.4.1 (2020-02-02)
|
||||
Fix invalid free() after failed realloc() (GHSA-gcx3-7m76-287p)
|
||||
Avoid overflows in allocation for packed fields.
|
||||
Verify stream size before allocating string / bytes.
|
||||
Add workaround for avr-libc realloc() bug (#475)
|
||||
Fix bug with field numbers >255 (#407)
|
||||
Fix compilation error on platforms without uint8_t (#485)
|
||||
Fix warnings on Python3.8 (#399, #467)
|
||||
Make fixed_count option work when combined with FT_POINTER.
|
||||
Add missing #define for submsg callbacks, add regression test (#472)
|
||||
Fix ImportError when using generator/protoc with Python 3
|
||||
Remove accidental debug code in generator
|
||||
Reduce stack usage (#484)
|
||||
Remove PB_FIELDINFO_WIDTH option (#473)
|
||||
Add nanopb-specific package name option (#422)
|
||||
Add testcase for Any type (#163)
|
||||
Add exclude option also from .proto/.options
|
||||
Set default include path in the grpc_tools protoc wrapper.
|
||||
Add workaround for python-protobuf 3.6.1 bug (#478)
|
||||
Detect invalid wire type when decoding fields.
|
||||
Improved fuzz testing
|
||||
|
||||
nanopb-0.4.0 (2019-12-20)
|
||||
New field descriptor format.
|
||||
Make nanopb_generator automatically compile .proto files (#462)
|
||||
Allow installing as Python package from pip (#460)
|
||||
Use protoc from grpcio-tools Python package if available (#463)
|
||||
Change proto3 message types to be optional (#308, #452)
|
||||
Add pb_decode_ex(), pb_encode_ex() functions.
|
||||
Automatically rebuild nanopb_pb2.py
|
||||
Use plugin.proto that comes with python-protobuf (#234)
|
||||
|
||||
Allow specifying a per-message callback. (#175)
|
||||
Improve callback handling inside oneofs. (#175)
|
||||
|
||||
Introduce new compile time flag: PB_VALIDATE_UTF8 (#437)
|
||||
Add TypenameMangling.M_PACKAGE_INITIALS (#394)
|
||||
Introduce new compile time flag: PB_ENCODE_ARRAYS_UNPACKED (#427)
|
||||
Add default_has option (#423)
|
||||
Add option for including extra files from .pb.h
|
||||
Add generator option to error out on unmatched options (#458)
|
||||
Generator: Allow comma separated options in plugin mode (#343)
|
||||
Allow comma-separated option parsing to handle `#include` (#450)
|
||||
Remove timestamp from generated files by default, add -t to keep it.
|
||||
Make --no-strip-path default (#326)
|
||||
Fix .options file case sensitivity on Windows.
|
||||
Fix generator error with mangle_names option (#380)
|
||||
Take int_size setting into account in calculating message sizes (#373)
|
||||
.gitignore: don't ignore generator-bin files (#419)
|
||||
Cleanup .pb.h header format
|
||||
|
||||
Make tests run on AVR and STM32
|
||||
Add PB_CONVERT_DOUBLE_FLOAT setting to convert doubles on AVR.
|
||||
Store field descriptor constants in flash on AVR (#464)
|
||||
Added "f" suffix to const float declarations. (#453)
|
||||
Fix clang-tidy warnings about using signed integers in binary bitwise operations (#451)
|
||||
Add C++ message descriptors helper (#384)
|
||||
Implement conan recipe (#378)
|
||||
CMake: Split nanopb_out command (#454)
|
||||
CMake: install created shared library(dll) in windows to the binary folder (#447)
|
||||
|
||||
nanopb-0.3.9.8 (2021-03-22)
|
||||
Fix invalid free() with oneof (#647, GHSA-7mv5-5mxh-qg88)
|
||||
Don't generate lines with trailing spaces (#622)
|
||||
Verify stream size before allocating string / bytes (#620)
|
||||
|
||||
nanopb-0.3.9.7 (2020-11-25)
|
||||
Fix memory leak with oneofs and PB_ENABLE_MALLOC (#615, GHSA-85rr-4rh9-hhwh)
|
||||
Fix unsigned enums not working correctly inside OneOf (#611)
|
||||
Add '--version' option to nanopb_generator.py (#607)
|
||||
SwiftPM rule updates (#567, #585)
|
||||
|
||||
nanopb-0.3.9.6 (2020-06-23)
|
||||
Fix buffer overflow when encoding bytes with size set to 65535 (#547, GHSA-3p39-mfxg-hrq4)
|
||||
Fix proto3 submessage improperly considered empty (#504)
|
||||
Fix ImportError when using generator/protoc with Python 3
|
||||
Add build rules for Swift package manager (#549)
|
||||
|
||||
nanopb-0.3.9.5 (2020-02-02)
|
||||
Fix invalid free() after failed realloc() (GHSA-gcx3-7m76-287p)
|
||||
Add workaround for avr-libc realloc() bug (#475)
|
||||
Fix empty submessages getting encoded in proto3 mode (#395)
|
||||
Avoid overflows in allocation for packed fields.
|
||||
|
||||
nanopb-0.3.9.4 (2019-10-13)
|
||||
Fix undefined behavior with bool fields (#434)
|
||||
Fix enum min/max defines when values are not in order (#405)
|
||||
Fix network_server socket example with zero-length strings (#421)
|
||||
Don't call stream read callback with count=0 (#421)
|
||||
Add compile time flag PB_ENCODE_ARRAYS_UNPACKED (#427)
|
||||
|
||||
nanopb-0.3.9.3 (2019-03-08)
|
||||
NOTE: nanopb-0.3.9.3.tar.gz before 2019-03-21 was accidentally from 0.4 branch (#388)
|
||||
Fix fixed size and callback repeated fields inside proto3 submessages (#376, #382, #386)
|
||||
Fix incorrect PB_STATIC_ASSERT for bytes inside oneof (#363)
|
||||
Fix generator error with mangle_names option (#380)
|
||||
Generator: Allow comma separated options in plugin mode (#343)
|
||||
|
||||
nanopb-0.3.9.2 (2018-11-10)
|
||||
Erroneous free() when using callbacks combined with PB_ENABLE_MALLOC (#346)
|
||||
Fix possible null-pointer dereference in decode_callback_field (#342)
|
||||
Fix FindNanopb.cmake on Windows (#335)
|
||||
Fix large generator memory usage with oneof fields (#338)
|
||||
Fix error in splint test (#359)
|
||||
Allow cmake to build as a shared library (#352, #353)
|
||||
Add --no-strip-path command line option (#326)
|
||||
Option for flattening nested protobuf names (#333)
|
||||
Documentation fixes (#329, #350, #358)
|
||||
Better error messages (#351)
|
||||
|
||||
nanopb-0.3.9.1 (2018-04-14)
|
||||
Fix handling of special characters in string/bytes default values (issue #322)
|
||||
Fix encoding of negative numbers with PB_WITHOUT_64BIT (#285)
|
||||
Fix _zero initializer for enums that don't begin at 0. (#295)
|
||||
Multiple CMake fixes (#296, #299, #304, #312, #320)
|
||||
Fix compiler warnings (#305)
|
||||
Fix scons rules for Python 3
|
||||
Add check for large extension field number (issue #306)
|
||||
Updated included descriptor.proto version (#314)
|
||||
Resolve oneof sizes symbolically when needed (#311)
|
||||
Add fixed_count option (#260)
|
||||
Add some verbose prints in generator (issue #238)
|
||||
Add test/example of using 'map' type. (#289)
|
||||
|
||||
nanopb-0.3.9 (2017-09-23)
|
||||
Fix bugs in proto3 encoding of submessages (#256)
|
||||
Fix message size calculation for arrays of size 1 (#253)
|
||||
Fix segfault with FT_CALLBACK inside FT_POINTER (#259)
|
||||
Properly detect truncated tags in corrupted messages (#277)
|
||||
Make pb_decode_varint32 overflow checks exact (#258)
|
||||
Add option to build without 64-bit support (#86)
|
||||
Add options to define source and header file extensions (#264)
|
||||
Add pb_en/decode_nullterminated() (part of #278)
|
||||
Add pb_decode_delimited_noinit (#284)
|
||||
CMake: add dependency for .options file (#265)
|
||||
CMake: change use of relative paths (#250,#271,#273)
|
||||
Better error message for missing max_size option (#281)
|
||||
Travis-CI build fixes (#283)
|
||||
Add Bazel build system file (#266)
|
||||
|
||||
nanopb-0.3.8 (2017-03-05)
|
||||
Fix problems with multiple oneofs in same message (#229)
|
||||
Zero-valued extension fields were mistakenly ignored by encoder (#242)
|
||||
Multiple fixes related to proto3 mode (#242, #245, #247, #249)
|
||||
Fix potential unaligned access (#226, #227)
|
||||
Fix documentation for protoc --plugin argument (#239)
|
||||
Extend inline / fixed length bytes array support (#244)
|
||||
Add new option max_length for strings (#107)
|
||||
Make string substream API more robust (#230)
|
||||
Make pb_decode_varint32 public API (#231)
|
||||
Allow overriding proto3 mode (#228)
|
||||
Add optional enum->string mapping function (#223)
|
||||
Add transitional options.proto file (#241)
|
||||
Add better error message on Python library version incompatibility (#240)
|
||||
Include version number in PlatformIO library.json (#222)
|
||||
CMake build script changes (#236, #237)
|
||||
Change download links to https
|
||||
Improvements to test cases.
|
||||
|
||||
nanopb-0.3.7 (2016-10-30)
|
||||
Add support for proto3-style singular fields (#182, #206, #216)
|
||||
Updated binary package protoc to version 3.1.0
|
||||
Add FT_INLINE allocation of bytes fields (#211)
|
||||
Include package name in include guard (#207)
|
||||
Fix missing warning with large bytes fields (issue #220)
|
||||
Added CMake project (#208)
|
||||
Add bazel BUILD file for nanopb (#209)
|
||||
Added an AUTHORS file (#211)
|
||||
Documentation updates
|
||||
Improvements to test cases.
|
||||
|
||||
nanopb-0.3.6 (2016-06-19)
|
||||
Protect against corrupted _count fields in pb_release (#205)
|
||||
Fix error in STATIC_ASSERT with multiple files (#203)
|
||||
Add -D option to specify output directory (#193)
|
||||
Generate MIN/MAX/ARRAYSIZE defines for enums (#194)
|
||||
Generate comments about uncalculable message sizes (#195)
|
||||
Documentation updates (#196, #201)
|
||||
Improvements to test cases.
|
||||
|
||||
nanopb-0.3.5 (2016-02-13)
|
||||
NOTE: If you are using pb_syshdr.h, you will need to add uint_least8_t
|
||||
definition. See docs/migration.rst for details.
|
||||
|
||||
Fix generator crash with Enum inside Oneof (#188)
|
||||
Fix some generator regressions related to .options file path (#172)
|
||||
Add support for platforms without uint8_t (#191)
|
||||
Allow const parameter to pb_istream_from_buffer (#152)
|
||||
Ignore null pointers in pb_release() (#183)
|
||||
Add support for anonymous unions (#184)
|
||||
Add Python3 support to the generator (#169)
|
||||
Add code generator insertion points to generated files (#178)
|
||||
Improvements to CMake script (#181)
|
||||
Improvements to test cases.
|
||||
|
||||
nanopb-0.3.4 (2015-09-26)
|
||||
Fix handling of unsigned 8- and 16-bit enums (issue 164)
|
||||
Fix generator on systems where python = python3. (issue 155)
|
||||
Fix compiler warning on GCC 5.x (issue 171)
|
||||
Make the generator better handle imported .protos (issue 165)
|
||||
Add packed_enum option to generator.
|
||||
Add syntax= line to .proto files (issue 167)
|
||||
Add PlatformIO registry manifest file. (pr 156)
|
||||
|
||||
nanopb-0.3.3 (2015-04-10)
|
||||
Fix missing files in Linux binary package (issue 146)
|
||||
Fix generator bug when oneof is first field in a message. (issue 142)
|
||||
Fix generator error when long_names:false is combined with Oneofs. (issue 147)
|
||||
Fix oneof submessage initialization bug. (issue 149)
|
||||
Fix problem with plugin options on Python 2.7.2 and older. (issue 153)
|
||||
Fix crash when callback is inside oneof field. (issue 148)
|
||||
Switch to .tar.gz format for Mac OS X packages. (issue 154)
|
||||
Always define enum long names so that cross-file references work. (issue 118)
|
||||
Add msgid generator option. (issue 151)
|
||||
Improve comment support in .options files. (issue 145)
|
||||
Updates for the CMake rule file, add cmake example.
|
||||
Better error messages for syntax errors in .options file
|
||||
|
||||
nanopb-0.3.2 (2015-01-24)
|
||||
Fix memory leaks with PB_ENABLE_MALLOC with some submessage hierarchies (issue 138)
|
||||
Implement support for oneofs (C unions). (issues 131, 141)
|
||||
Add int_size option for generator (issue 139)
|
||||
Add compilation option to disable struct packing. (issue 136)
|
||||
Change PB_RETURN_ERROR() macro to avoid compiler warnings (issue 140)
|
||||
Fix build problems with protoc 3.0.0
|
||||
Add support for POINTER type in extensions
|
||||
Initialize also extension fields to defaults in pb_decode().
|
||||
Detect too large varint values when decoding.
|
||||
|
||||
nanopb-0.3.1 (2014-09-11)
|
||||
Fix security issue due to size_t overflows. (issue 132)
|
||||
Fix memory leak with duplicated fields and PB_ENABLE_MALLOC
|
||||
Fix crash if pb_release() is called twice.
|
||||
Fix cyclic message support (issue 130)
|
||||
Fix error in generated initializers for repeated pointer fields.
|
||||
Improve tests (issues 113, 126)
|
||||
|
||||
nanopb-0.3.0 (2014-08-26)
|
||||
NOTE: See docs/migration.html or online at
|
||||
http://koti.kapsi.fi/~jpa/nanopb/docs/migration.html
|
||||
for changes in this version. Most importantly, you need to add
|
||||
pb_common.c to the list of files to compile.
|
||||
|
||||
Separated field iterator logic to pb_common.c (issue 128)
|
||||
Change the _count fields to use pb_size_t datatype (issue 82)
|
||||
Added PB_ prefix to macro names (issue 106)
|
||||
Added #if version guard to generated files (issue 129)
|
||||
Added migration document
|
||||
|
||||
nanopb-0.2.9.5 (2020-06-23)
|
||||
Fix buffer overflow when encoding bytes with size set to 65535 (#547, GHSA-3p39-mfxg-hrq4)
|
||||
Backport Python 3 and protoc 3.x fixes to test cases
|
||||
|
||||
nanopb-0.2.9.4 (2020-02-02)
|
||||
Fix invalid free() after failed realloc() (GHSA-gcx3-7m76-287p)
|
||||
Add workaround for avr-libc realloc() bug (#475)
|
||||
|
||||
nanopb-0.2.9.3 (2016-06-19)
|
||||
Protect against corrupted _count fields in pb_release (#205)
|
||||
|
||||
nanopb-0.2.9.2 (2015-01-24)
|
||||
Fix memory leaks with PB_ENABLE_MALLOC with some submessage hierarchies (issue 138)
|
||||
Fix compilation error with generated initializers for repeated pointer fields
|
||||
|
||||
nanopb-0.2.9.1 (2014-09-11)
|
||||
Fix security issue due to size_t overflows. (issue 132)
|
||||
Fix memory leak with duplicated fields and PB_ENABLE_MALLOC
|
||||
Fix crash if pb_release() is called twice.
|
||||
|
||||
nanopb-0.2.9 (2014-08-09)
|
||||
NOTE: If you are using the -e option with the generator, you have
|
||||
to prepend . to the argument to get the same behaviour as before.
|
||||
|
||||
Do not automatically add a dot with generator -e option. (issue 122)
|
||||
Fix problem with .options file and extension fields. (issue 125)
|
||||
Don't use SIZE_MAX macro, as it is not in C89. (issue 120)
|
||||
Generate #defines for initializing message structures. (issue 79)
|
||||
Add skip_message option to generator. (issue 121)
|
||||
Add PB_PACKED_STRUCT support for Keil MDK-ARM toolchain (issue 119)
|
||||
Give better messages about the .options file path. (issue 124)
|
||||
Improved tests
|
||||
|
||||
nanopb-0.2.8 (2014-05-20)
|
||||
Fix security issue with PB_ENABLE_MALLOC. (issue 117)
|
||||
Add option to not add timestamps to .pb.h and .pb.c preambles. (issue 115)
|
||||
Documentation updates
|
||||
Improved tests
|
||||
|
||||
nanopb-0.2.7 (2014-04-07)
|
||||
Fix bug with default values for extension fields (issue 111)
|
||||
Fix some MISRA-C warnings (issue 91)
|
||||
Implemented optional malloc() support (issue 80)
|
||||
Changed pointer-type bytes field datatype
|
||||
Add a "found" field to pb_extension_t (issue 112)
|
||||
Add convenience function pb_get_encoded_size() (issue 16)
|
||||
|
||||
nanopb-0.2.6 (2014-02-15)
|
||||
Fix generator error with bytes callback fields (issue 99)
|
||||
Fix warnings about large integer constants (issue 102)
|
||||
Add comments to where STATIC_ASSERT is used (issue 96)
|
||||
Add warning about unknown field names on .options (issue 105)
|
||||
Move descriptor.proto to google/protobuf subdirectory (issue 104)
|
||||
Improved tests
|
||||
|
||||
nanopb-0.2.5 (2014-01-01)
|
||||
Fix a bug with encoding negative values in int32 fields (issue 97)
|
||||
Create binary packages of the generator + dependencies (issue 47)
|
||||
Add support for pointer-type fields to the encoder (part of issue 80)
|
||||
Fixed path in FindNanopb.cmake (issue 94)
|
||||
Improved tests
|
||||
|
||||
nanopb-0.2.4 (2013-11-07)
|
||||
Remove the deprecated NANOPB_INTERNALS functions from public API.
|
||||
Document the security model.
|
||||
Check array and bytes max sizes when encoding (issue 90)
|
||||
Add #defines for maximum encoded message size (issue 89)
|
||||
Add #define tags for extension fields (issue 93)
|
||||
Fix MISRA C violations (issue 91)
|
||||
Clean up pb_field_t definition with typedefs.
|
||||
|
||||
nanopb-0.2.3 (2013-09-18)
|
||||
Improve compatibility by removing ternary operator from initializations (issue 88)
|
||||
Fix build error on Visual C++ (issue 84, patch by Markus Schwarzenberg)
|
||||
Don't stop on unsupported extension fields (issue 83)
|
||||
Add an example pb_syshdr.h file for non-C99 compilers
|
||||
Reorganize tests and examples into subfolders (issue 63)
|
||||
Switch from Makefiles to scons for building the tests
|
||||
Make the tests buildable on Windows
|
||||
|
||||
nanopb-0.2.2 (2013-08-18)
|
||||
Add support for extension fields (issue 17)
|
||||
Fix unknown fields in empty message (issue 78)
|
||||
Include the field tags in the generated .pb.h file.
|
||||
Add pb_decode_delimited and pb_encode_delimited wrapper functions (issue 74)
|
||||
Add a section in top of pb.h for changing compilation settings (issue 76)
|
||||
Documentation improvements (issues 12, 77 and others)
|
||||
Improved tests
|
||||
|
||||
nanopb-0.2.1 (2013-04-14)
|
||||
NOTE: The default callback function signature has changed.
|
||||
If you don't want to update your code, define PB_OLD_CALLBACK_STYLE.
|
||||
|
||||
Change the callback function to use void** (issue 69)
|
||||
Add support for defining the nanopb options in a separate file (issue 12)
|
||||
Add support for packed structs in IAR and MSVC (in addition to GCC) (issue 66)
|
||||
Implement error message support for the encoder side (issue 7)
|
||||
Handle unterminated strings when encoding (issue 68)
|
||||
Fix bug with empty strings in repeated string callbacks (issue 73)
|
||||
Fix regression in 0.2.0 with optional callback fields (issue 70)
|
||||
Fix bugs with empty message types (issues 64, 65)
|
||||
Fix some compiler warnings on clang (issue 67)
|
||||
Some portability improvements (issues 60, 62)
|
||||
Various new generator options
|
||||
Improved tests
|
||||
|
||||
nanopb-0.2.0 (2013-03-02)
|
||||
NOTE: This release requires you to regenerate all .pb.c
|
||||
files. Files generated by older versions will not
|
||||
compile anymore.
|
||||
|
||||
Reformat generated .pb.c files using macros (issue 58)
|
||||
Rename PB_HTYPE_ARRAY -> PB_HTYPE_REPEATED
|
||||
Separate PB_HTYPE to PB_ATYPE and PB_HTYPE
|
||||
Move STATIC_ASSERTs to .pb.c file
|
||||
Added CMake file (by Pavel Ilin)
|
||||
Add option to give file extension to generator (by Michael Haberler)
|
||||
Documentation updates
|
||||
|
||||
nanopb-0.1.9 (2013-02-13)
|
||||
Fixed error message bugs (issues 52, 56)
|
||||
Sanitize #ifndef filename (issue 50)
|
||||
Performance improvements
|
||||
Add compile-time option PB_BUFFER_ONLY
|
||||
Add Java package name to nanopb.proto
|
||||
Check for sizeof(double) == 8 (issue 54)
|
||||
Added generator option to ignore some fields. (issue 51)
|
||||
Added generator option to make message structs packed. (issue 49)
|
||||
Add more test cases.
|
||||
|
||||
nanopb-0.1.8 (2012-12-13)
|
||||
Fix bugs in the enum short names introduced in 0.1.7 (issues 42, 43)
|
||||
Fix STATIC_ASSERT macro when using multiple .proto files. (issue 41)
|
||||
Fix missing initialization of istream.errmsg
|
||||
Make tests/Makefile work for non-gcc compilers (issue 40)
|
||||
|
||||
nanopb-0.1.7 (2012-11-11)
|
||||
Remove "skip" mode from pb_istream_t callbacks. Example implementation had a bug. (issue 37)
|
||||
Add option to use shorter names for enum values (issue 38)
|
||||
Improve options support in generator (issues 12, 30)
|
||||
Add nanopb version number to generated files (issue 36)
|
||||
Add extern "C" to generated headers (issue 35)
|
||||
Add names for structs to allow forward declaration (issue 39)
|
||||
Add buffer size check in example (issue 34)
|
||||
Fix build warnings on MS compilers (issue 33)
|
||||
|
||||
nanopb-0.1.6 (2012-09-02)
|
||||
Reorganize the field decoder interface (issue 2)
|
||||
Improve performance in submessage decoding (issue 28)
|
||||
Implement error messages in the decoder side (issue 7)
|
||||
Extended testcases (alltypes test is now complete).
|
||||
Fix some compiler warnings (issues 25, 26, 27, 32).
|
||||
|
||||
nanopb-0.1.5 (2012-08-04)
|
||||
Fix bug in decoder with packed arrays (issue 23).
|
||||
Extended testcases.
|
||||
Fix some compiler warnings.
|
||||
|
||||
nanopb-0.1.4 (2012-07-05)
|
||||
Add compile-time options for easy-to-use >255 field support.
|
||||
Improve the detection of missing required fields.
|
||||
Added example on how to handle union messages.
|
||||
Fix generator error with .proto without messages.
|
||||
Fix problems that stopped the code from compiling with some compilers.
|
||||
Fix some compiler warnings.
|
||||
|
||||
nanopb-0.1.3 (2012-06-12)
|
||||
Refactor the field encoder interface.
|
||||
Improve generator error messages (issue 5)
|
||||
Add descriptor.proto into the #include exclusion list
|
||||
Fix some compiler warnings.
|
||||
|
||||
nanopb-0.1.2 (2012-02-15)
|
||||
Make the generator to generate include for other .proto files (issue 4).
|
||||
Fixed generator not working on Windows (issue 3)
|
||||
|
||||
nanopb-0.1.1 (2012-01-14)
|
||||
Fixed bug in encoder with 'bytes' fields (issue 1).
|
||||
Fixed a bug in the generator that caused a compiler error on sfixed32 and sfixed64 fields.
|
||||
Extended testcases.
|
||||
|
||||
nanopb-0.1.0 (2012-01-06)
|
||||
First stable release.
|
32
third_party/nanopb/CONTRIBUTING.md
vendored
Normal file
32
third_party/nanopb/CONTRIBUTING.md
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
Contributing to Nanopb development
|
||||
==================================
|
||||
|
||||
Reporting issues and requesting features
|
||||
----------------------------------------
|
||||
|
||||
Feel free to report any issues you see or features you would like
|
||||
to see in the future to the Github issue tracker. Using the templates
|
||||
below is preferred:
|
||||
|
||||
* [Report a bug](https://github.com/nanopb/nanopb/issues/new?body=**Steps%20to%20reproduce%20the%20issue**%0a%0a1.%0a2.%0a3.%0a%0a**What%20happens?**%0A%0A**What%20should%20happen?**&labels=Type-Defect)
|
||||
* [Request a feature](https://github.com/nanopb/nanopb/issues/new?body=**What%20should%20the%20feature%20do?**%0A%0A**In%20what%20situation%20would%20the%20feature%20be%20useful?**&labels=Type-Enhancement)
|
||||
|
||||
Requesting help
|
||||
---------------
|
||||
|
||||
If there is something strange going on, but you do not know if
|
||||
it is actually a bug in nanopb, try asking first on the
|
||||
[discussion forum](https://groups.google.com/forum/#!forum/nanopb).
|
||||
|
||||
Pull requests
|
||||
-------------
|
||||
|
||||
Pull requests are welcome!
|
||||
|
||||
If it is not obvious from the commit message, please indicate the
|
||||
same information as you would for an issue report:
|
||||
|
||||
* What functionality it fixes/adds.
|
||||
* How can the problem be reproduced / when would the feature be useful.
|
||||
|
||||
|
79
third_party/nanopb/LICENSE.txt
vendored
Normal file
79
third_party/nanopb/LICENSE.txt
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
Copyright (c) 2011 Petteri Aimonen <jpa at nanopb.mail.kapsi.fi>
|
||||
|
||||
This software is provided 'as-is', without any express or
|
||||
implied warranty. In no event will the authors be held liable
|
||||
for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
|
||||
|
||||
|
||||
The function generator/nanopb_generator.py:toposort2 is licensed under the MIT
|
||||
License:
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2010 Paddy McCarthy
|
||||
|
||||
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:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
The function pb_common.c:pb_validate_utf8 is licensed under the following terms:
|
||||
|
||||
Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/> -- 2005-03-30
|
||||
License: http://www.cl.cam.ac.uk/~mgk25/short-license.html
|
||||
|
||||
Short code license
|
||||
If you have reached this web page because you found its URL included as a license-reference comment in a short piece of published computer software source code by its author(s), next to their name, as in, for example,
|
||||
|
||||
Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/> -- 1999-12-31
|
||||
License: https://www.cl.cam.ac.uk/~mgk25/short-license.html
|
||||
then you can assume the following:
|
||||
|
||||
This code was published by its author(s) as an easily reusable piece of free software, for example to demonstrate some particular programming practice. It is likely too short or obvious to skilled programmers to fall under, or deserve, the protection of copyright legislation. It is also likely to be useless on its own, unless verified and integrated into a larger program by an experienced software engineer, and therefore no consumer protection, warranty or liability rights apply either. Therefore, its author(s) refused to disfigure its appearance with a lengthy copyright license text.
|
||||
|
||||
Nevertheless, overly cautious lawyers (possibly as part of a “due diligence exercise”) occasionally contact authors of such short code snippets for a formal copyright license.
|
||||
|
||||
Therefore, the author(s) agree(s) to clarify that, at the user’s choice, the code can be used under any of the following licenses, or any compatible with them:
|
||||
|
||||
Apache License, 2.0
|
||||
BSD license
|
||||
GNU General Public License (GPL)
|
||||
GNU Library or "Lesser" General Public License (LGPL)
|
||||
MIT license
|
||||
Mozilla Public License 1.1 (MPL)
|
||||
Common Development and Distribution License
|
||||
Eclipse Public License
|
||||
CC0
|
||||
Markus Kuhn
|
63
third_party/nanopb/Package.swift
vendored
Normal file
63
third_party/nanopb/Package.swift
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
// swift-tools-version:5.0
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "nanopb",
|
||||
products: [
|
||||
.library(
|
||||
name: "nanopb",
|
||||
targets: ["nanopb"]
|
||||
)
|
||||
],
|
||||
|
||||
targets: [
|
||||
.target(
|
||||
name: "nanopb",
|
||||
path: ".",
|
||||
sources: [
|
||||
"pb.h",
|
||||
"pb_common.h",
|
||||
"pb_common.c",
|
||||
"pb_decode.h",
|
||||
"pb_decode.c",
|
||||
"pb_encode.h",
|
||||
"pb_encode.c"
|
||||
],
|
||||
publicHeadersPath: "spm_headers",
|
||||
cSettings: [
|
||||
.define("PB_FIELD_32BIT", to: "1"),
|
||||
.define("PB_NO_PACKED_STRUCTS", to: "1"),
|
||||
.define("PB_ENABLE_MALLOC", to: "1"),
|
||||
]
|
||||
),
|
||||
.testTarget(
|
||||
name: "swift-test",
|
||||
dependencies: [
|
||||
"nanopb",
|
||||
],
|
||||
path: "spm-test/swift",
|
||||
cSettings: [
|
||||
.headerSearchPath("../"),
|
||||
.define("PB_FIELD_32BIT", to: "1"),
|
||||
.define("PB_NO_PACKED_STRUCTS", to: "1"),
|
||||
.define("PB_ENABLE_MALLOC", to: "1"),
|
||||
]
|
||||
),
|
||||
.testTarget(
|
||||
name: "objc-test",
|
||||
dependencies: [
|
||||
"nanopb",
|
||||
],
|
||||
path: "spm-test/objc",
|
||||
cSettings: [
|
||||
.headerSearchPath("../"),
|
||||
.define("PB_FIELD_32BIT", to: "1"),
|
||||
.define("PB_NO_PACKED_STRUCTS", to: "1"),
|
||||
.define("PB_ENABLE_MALLOC", to: "1"),
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
|
99
third_party/nanopb/README.md
vendored
Normal file
99
third_party/nanopb/README.md
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
Nanopb - Protocol Buffers for Embedded Systems
|
||||
==============================================
|
||||
|
||||

|
||||

|
||||
|
||||
Nanopb is a small code-size Protocol Buffers implementation in ansi C. It is
|
||||
especially suitable for use in microcontrollers, but fits any memory
|
||||
restricted system.
|
||||
|
||||
* **Homepage:** https://jpa.kapsi.fi/nanopb/
|
||||
* **Git repository:** https://github.com/nanopb/nanopb/
|
||||
* **Documentation:** https://jpa.kapsi.fi/nanopb/docs/
|
||||
* **Forum:** https://groups.google.com/forum/#!forum/nanopb
|
||||
* **Stable version downloads:** https://jpa.kapsi.fi/nanopb/download/
|
||||
* **Pre-release binary packages:** https://github.com/nanopb/nanopb/actions/workflows/binary_packages.yml
|
||||
|
||||
|
||||
Using the nanopb library
|
||||
------------------------
|
||||
To use the nanopb library, you need to do two things:
|
||||
|
||||
1. Compile your .proto files for nanopb, using `protoc`.
|
||||
2. Include *pb_encode.c*, *pb_decode.c* and *pb_common.c* in your project.
|
||||
|
||||
The easiest way to get started is to study the project in "examples/simple".
|
||||
It contains a Makefile, which should work directly under most Linux systems.
|
||||
However, for any other kind of build system, see the manual steps in
|
||||
README.txt in that folder.
|
||||
|
||||
|
||||
Generating the headers
|
||||
----------------------
|
||||
Protocol Buffers messages are defined in a `.proto` file, which follows a standard
|
||||
format that is compatible with all Protocol Buffers libraries. To use it with nanopb,
|
||||
you need to generate `.pb.c` and `.pb.h` files from it:
|
||||
|
||||
python generator/nanopb_generator.py myprotocol.proto # For source checkout
|
||||
generator-bin/nanopb_generator myprotocol.proto # For binary package
|
||||
|
||||
(Note: For instructions for nanopb-0.3.9.x and older, see the documentation
|
||||
of that particular version [here](https://github.com/nanopb/nanopb/blob/maintenance_0.3/README.md))
|
||||
|
||||
The binary packages for Windows, Linux and Mac OS X should contain all necessary
|
||||
dependencies, including Python, python-protobuf library and protoc. If you are
|
||||
using a git checkout or a plain source distribution, you will need to install
|
||||
Python separately. Once you have Python, you can install the other dependencies
|
||||
with `pip install --upgrade protobuf grpcio-tools`.
|
||||
|
||||
You can further customize the header generation by creating an `.options` file.
|
||||
See [documentation](https://jpa.kapsi.fi/nanopb/docs/concepts.html#modifying-generator-behaviour) for details.
|
||||
|
||||
|
||||
Running the tests
|
||||
-----------------
|
||||
If you want to perform further development of the nanopb core, or to verify
|
||||
its functionality using your compiler and platform, you'll want to run the
|
||||
test suite. The build rules for the test suite are implemented using Scons,
|
||||
so you need to have that installed (ex: `sudo apt install scons` or `pip install scons`).
|
||||
To run the tests:
|
||||
|
||||
cd tests
|
||||
scons
|
||||
|
||||
This will show the progress of various test cases. If the output does not
|
||||
end in an error, the test cases were successful.
|
||||
|
||||
Note: Mac OS X by default aliases 'clang' as 'gcc', while not actually
|
||||
supporting the same command line options as gcc does. To run tests on
|
||||
Mac OS X, use: `scons CC=clang CXX=clang`. Same way can be used to run
|
||||
tests with different compilers on any platform.
|
||||
|
||||
For embedded platforms, there is currently support for running the tests
|
||||
on STM32 discovery board and [simavr](https://github.com/buserror/simavr)
|
||||
AVR simulator. Use `scons PLATFORM=STM32` and `scons PLATFORM=AVR` to run
|
||||
these tests.
|
||||
|
||||
|
||||
Build systems and integration
|
||||
-----------------------------
|
||||
Nanopb C code itself is designed to be portable and easy to build
|
||||
on any platform. Often the bigger hurdle is running the generator which
|
||||
takes in the `.proto` files and outputs `.pb.c` definitions.
|
||||
|
||||
There exist build rules for several systems:
|
||||
|
||||
* **Makefiles**: `extra/nanopb.mk`, see `examples/simple`
|
||||
* **CMake**: `extra/FindNanopb.cmake`, see `examples/cmake`
|
||||
* **SCons**: `tests/site_scons` (generator only)
|
||||
* **Bazel**: `BUILD` in source root
|
||||
* **Conan**: `conanfile.py` in source root
|
||||
* **PlatformIO**: https://platformio.org/lib/show/431/Nanopb
|
||||
* **PyPI/pip**: https://pypi.org/project/nanopb/
|
||||
* **vcpkg**: https://vcpkg.info/port/nanopb
|
||||
|
||||
And also integration to platform interfaces:
|
||||
|
||||
* **Arduino**: http://platformio.org/lib/show/1385/nanopb-arduino
|
||||
|
1
third_party/nanopb/WORKSPACE
vendored
Normal file
1
third_party/nanopb/WORKSPACE
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
workspace(name = "com_github_nanopb_nanopb")
|
6
third_party/nanopb/build.py
vendored
Normal file
6
third_party/nanopb/build.py
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
from conan.packager import ConanMultiPackager
|
||||
|
||||
if __name__ == "__main__":
|
||||
builder = ConanMultiPackager(build_policy="outdated")
|
||||
builder.add_common_builds(shared_option_name=None)
|
||||
builder.run()
|
33
third_party/nanopb/conanfile.py
vendored
Normal file
33
third_party/nanopb/conanfile.py
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
from conans import ConanFile, CMake, tools
|
||||
from os import path
|
||||
|
||||
class NanoPbConan(ConanFile):
|
||||
name = "nanopb"
|
||||
version = "0.4.6"
|
||||
license = "zlib"
|
||||
url = "https://jpa.kapsi.fi/nanopb/"
|
||||
description = "Protocol Buffers with small code size"
|
||||
settings = "os_build", "compiler", "build_type", "arch"
|
||||
generators = "cmake"
|
||||
exports = '*'
|
||||
options = {
|
||||
"fPIC": [True, False],
|
||||
}
|
||||
default_options = {
|
||||
"fPIC": True,
|
||||
}
|
||||
|
||||
def configure(self):
|
||||
if self.settings.os_build == "Windows" and self.settings.compiler == "Visual Studio":
|
||||
del self.options.fPIC
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
cmake.configure(source_folder=path.join(self.source_folder, "conan-wrapper"))
|
||||
cmake.build()
|
||||
cmake.install()
|
||||
|
||||
def package_info(self):
|
||||
self.cpp_info.includedirs = ["include"]
|
||||
self.cpp_info.libdirs = ["lib"]
|
||||
self.cpp_info.libs = ["protobuf-nanopb"]
|
23
third_party/nanopb/docs/Makefile
vendored
Normal file
23
third_party/nanopb/docs/Makefile
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
INPUTS = index.md concepts.md reference.md security.md migration.md whats_new.md
|
||||
|
||||
all: $(INPUTS:.md=.html)
|
||||
|
||||
tmp_menu.html: $(INPUTS)
|
||||
echo '<div id="index">' > $@
|
||||
(echo '<h2>Documentation index</h2>'; \
|
||||
for file in $^; do echo -n '1. ['; sed -n '1 s!^# Nanopb: !! p' $$file; \
|
||||
echo -n "]("; echo $$file | sed 's/.md/.html)/' ; done;) | \
|
||||
pandoc -f markdown -t html5 >> $@
|
||||
echo '</div>' >> $@
|
||||
|
||||
%.html: %.md tmp_menu.html
|
||||
sed '1 s!#!%!' $< | \
|
||||
pandoc -s -f markdown -t html5 -c lsr.css --toc --toc-depth=4 \
|
||||
--variable 'header-includes=<link href="favicon.ico" type="image/x-icon" rel="shortcut icon" />' \
|
||||
--indented-code-classes=c \
|
||||
-o $@
|
||||
sed -i '/<nav/e cat feedback.html' $@
|
||||
sed -i 's/doc_page_name_placeholder/$</' $@
|
||||
sed -i 's!<nav[^>]*>!\0<b>Contents:</b>!' $@
|
||||
sed -i '/<nav/e cat tmp_menu.html' $@
|
||||
|
621
third_party/nanopb/docs/concepts.md
vendored
Normal file
621
third_party/nanopb/docs/concepts.md
vendored
Normal file
|
@ -0,0 +1,621 @@
|
|||
# Nanopb: Basic concepts
|
||||
|
||||
The things outlined here are the underlying concepts of the nanopb
|
||||
design.
|
||||
|
||||
## Proto files
|
||||
|
||||
All Protocol Buffers implementations use .proto files to describe the
|
||||
message format. The point of these files is to be a portable interface
|
||||
description language.
|
||||
|
||||
### Compiling .proto files for nanopb
|
||||
|
||||
Nanopb comes with a Python script to generate `.pb.c` and
|
||||
`.pb.h` files from the `.proto` definition:
|
||||
|
||||
user@host:~$ nanopb/generator/nanopb_generator.py message.proto
|
||||
Writing to message.pb.h and message.pb.c
|
||||
|
||||
Internally this script uses Google `protoc` to parse the
|
||||
input file. If you do not have it available, you may receive an error
|
||||
message. You can install either `grpcio-tools` Python
|
||||
package using `pip`, or the `protoc` compiler
|
||||
itself from `protobuf-compiler` distribution package.
|
||||
Generally the Python package is recommended, because nanopb requires
|
||||
protoc version 3.6 or newer to support all features, and some distributions come with an older
|
||||
version.
|
||||
|
||||
### Modifying generator behaviour
|
||||
|
||||
Using generator options, you can set maximum sizes for fields in order
|
||||
to allocate them statically. The preferred way to do this is to create
|
||||
an .options file with the same name as your .proto file:
|
||||
|
||||
# Foo.proto
|
||||
message Foo {
|
||||
required string name = 1;
|
||||
}
|
||||
|
||||
# Foo.options
|
||||
Foo.name max_size:16
|
||||
|
||||
For more information on this, see the [Proto file
|
||||
options](reference.html#proto-file-options) section in the reference
|
||||
manual.
|
||||
|
||||
## Streams
|
||||
|
||||
Nanopb uses streams for accessing the data in encoded format. The stream
|
||||
abstraction is very lightweight, and consists of a structure
|
||||
(`pb_ostream_t` or `pb_istream_t`) which contains a pointer to a
|
||||
callback function.
|
||||
|
||||
There are a few generic rules for callback functions:
|
||||
|
||||
1) Return false on IO errors. The encoding or decoding process will
|
||||
abort immediately.
|
||||
2) Use state to store your own data, such as a file descriptor.
|
||||
3) `bytes_written` and `bytes_left` are updated by pb_write and
|
||||
pb_read.
|
||||
4) Your callback may be used with substreams. In this case
|
||||
`bytes_left`, `bytes_written` and `max_size` have smaller values
|
||||
than the original stream. Don't use these values to calculate
|
||||
pointers.
|
||||
5) Always read or write the full requested length of data. For example,
|
||||
POSIX `recv()` needs the `MSG_WAITALL` parameter to accomplish
|
||||
this.
|
||||
|
||||
### Output streams
|
||||
|
||||
struct _pb_ostream_t
|
||||
{
|
||||
bool (*callback)(pb_ostream_t *stream, const uint8_t *buf, size_t count);
|
||||
void *state;
|
||||
size_t max_size;
|
||||
size_t bytes_written;
|
||||
};
|
||||
|
||||
The `callback` for output stream may be NULL, in which case the stream
|
||||
simply counts the number of bytes written. In this case, `max_size` is
|
||||
ignored.
|
||||
|
||||
Otherwise, if `bytes_written` + bytes_to_be_written is larger than
|
||||
`max_size`, pb_write returns false before doing anything else. If you
|
||||
don\'t want to limit the size of the stream, pass SIZE_MAX.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
This is the way to get the size of the message without storing it
|
||||
anywhere:
|
||||
|
||||
Person myperson = ...;
|
||||
pb_ostream_t sizestream = {0};
|
||||
pb_encode(&sizestream, Person_fields, &myperson);
|
||||
printf("Encoded size is %d\n", sizestream.bytes_written);
|
||||
|
||||
**Example 2:**
|
||||
|
||||
Writing to stdout:
|
||||
|
||||
bool callback(pb_ostream_t `stream, const uint8_t `buf, size_t count)
|
||||
{
|
||||
FILE *file = (FILE*) stream->state;
|
||||
return fwrite(buf, 1, count, file) == count;
|
||||
}
|
||||
|
||||
pb_ostream_t stdoutstream = {&callback, stdout, SIZE_MAX, 0};
|
||||
|
||||
### Input streams
|
||||
|
||||
For input streams, there is one extra rule:
|
||||
|
||||
6) You don't need to know the length of the message in advance. After
|
||||
getting EOF error when reading, set `bytes_left` to 0 and return
|
||||
`false`. `pb_decode()` will detect this and if the EOF was in a proper
|
||||
position, it will return true.
|
||||
|
||||
Here is the structure:
|
||||
|
||||
struct _pb_istream_t
|
||||
{
|
||||
bool (*callback)(pb_istream_t *stream, uint8_t *buf, size_t count);
|
||||
void *state;
|
||||
size_t bytes_left;
|
||||
};
|
||||
|
||||
The `callback` must always be a function pointer. `Bytes_left` is an
|
||||
upper limit on the number of bytes that will be read. You can use
|
||||
SIZE_MAX if your callback handles EOF as described above.
|
||||
|
||||
**Example:**
|
||||
|
||||
This function binds an input stream to stdin:
|
||||
|
||||
bool callback(pb_istream_t *stream, uint8_t *buf, size_t count)
|
||||
{
|
||||
FILE *file = (FILE*)stream->state;
|
||||
bool status;
|
||||
|
||||
if (buf == NULL)
|
||||
{
|
||||
while (count-- && fgetc(file) != EOF);
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
status = (fread(buf, 1, count, file) == count);
|
||||
|
||||
if (feof(file))
|
||||
stream->bytes_left = 0;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
pb_istream_t stdinstream = {&callback, stdin, SIZE_MAX};
|
||||
|
||||
## Data types
|
||||
|
||||
Most Protocol Buffers datatypes have directly corresponding C datatypes,
|
||||
such as `int32` is `int32_t`, `float` is `float` and `bool` is `bool`. However, the
|
||||
variable-length datatypes are more complex:
|
||||
|
||||
1) Strings, bytes and repeated fields of any type map to callback
|
||||
functions by default.
|
||||
2) If there is a special option `(nanopb).max_size` specified in the
|
||||
.proto file, string maps to null-terminated char array and bytes map
|
||||
to a structure containing a char array and a size field.
|
||||
3) If `(nanopb).fixed_length` is set to `true` and
|
||||
`(nanopb).max_size` is also set, then bytes map to an inline byte
|
||||
array of fixed size.
|
||||
4) If there is a special option `(nanopb).max_count` specified on a
|
||||
repeated field, it maps to an array of whatever type is being
|
||||
repeated. Another field will be created for the actual number of
|
||||
entries stored.
|
||||
5) If `(nanopb).fixed_count` is set to `true` and
|
||||
`(nanopb).max_count` is also set, the field for the actual number
|
||||
of entries will not by created as the count is always assumed to be
|
||||
max count.
|
||||
|
||||
### Examples of .proto specifications vs. generated structure
|
||||
|
||||
**Simple integer field:**\
|
||||
.proto: `int32 age = 1;`\
|
||||
.pb.h: `int32_t age;`
|
||||
|
||||
**String with unknown length:**\
|
||||
.proto: `string name = 1;`\
|
||||
.pb.h: `pb_callback_t name;`
|
||||
|
||||
**String with known maximum length:**\
|
||||
.proto: `string name = 1 [(nanopb).max_length = 40];`\
|
||||
.pb.h: `char name[41];`
|
||||
|
||||
**Repeated string with unknown count:**\
|
||||
.proto: `repeated string names = 1;`\
|
||||
.pb.h: `pb_callback_t names;`
|
||||
|
||||
**Repeated string with known maximum count and size:**\
|
||||
.proto: `repeated string names = 1 [(nanopb).max_length = 40, (nanopb).max_count = 5];`\
|
||||
.pb.h: `size_t names_count;` `char names[5][41];`
|
||||
|
||||
**Bytes field with known maximum size:**\
|
||||
.proto: `bytes data = 1 [(nanopb).max_size = 16];`\
|
||||
.pb.h: `PB_BYTES_ARRAY_T(16) data;`, where the struct contains `{pb_size_t size; pb_byte_t bytes[n];}`
|
||||
|
||||
**Bytes field with fixed length:**\
|
||||
.proto: `bytes data = 1 [(nanopb).max_size = 16, (nanopb).fixed_length = true];`\
|
||||
.pb.h: `pb_byte_t data[16];`
|
||||
|
||||
**Repeated integer array with known maximum size:**\
|
||||
.proto: `repeated int32 numbers = 1 [(nanopb).max_count = 5];`\
|
||||
.pb.h: `pb_size_t numbers_count;` `int32_t numbers[5];`
|
||||
|
||||
**Repeated integer array with fixed count:**\
|
||||
.proto: `repeated int32 numbers = 1 [(nanopb).max_count = 5, (nanopb).fixed_count = true];`\
|
||||
.pb.h: `int32_t numbers[5];`
|
||||
|
||||
The maximum lengths are checked in runtime. If string/bytes/array
|
||||
exceeds the allocated length, `pb_decode()` will return false.
|
||||
|
||||
> **Note:** For the `bytes` datatype, the field length checking may not be
|
||||
exact. The compiler may add some padding to the `pb_bytes_t`
|
||||
structure, and the nanopb runtime doesn't know how much of the
|
||||
structure size is padding. Therefore it uses the whole length of the
|
||||
structure for storing data, which is not very smart but shouldn't cause
|
||||
problems. In practise, this means that if you specify
|
||||
`(nanopb).max_size=5` on a `bytes` field, you may be able to store 6
|
||||
bytes there. For the `string` field type, the length limit is exact.
|
||||
|
||||
> **Note:** The decoder only keeps track of one `fixed_count` repeated field at a time. Usually this it not an issue because all elements of a repeated field occur end-to-end. Interleaved array elements of several `fixed_count` repeated fields would be a valid protobuf message, but would get rejected by nanopb decoder with error `"wrong size for fixed count field"`.
|
||||
|
||||
## Field callbacks
|
||||
|
||||
When a field has dynamic length, nanopb cannot statically allocate
|
||||
storage for it. Instead, it allows you to handle the field in whatever
|
||||
way you want, using a callback function.
|
||||
|
||||
The [pb_callback_t](reference.html#pb-callback-t) structure contains a
|
||||
function pointer and a `void` pointer called `arg` you can use for
|
||||
passing data to the callback. If the function pointer is NULL, the field
|
||||
will be skipped. A pointer to the `arg` is passed to the function, so
|
||||
that it can modify it and retrieve the value.
|
||||
|
||||
The actual behavior of the callback function is different in encoding
|
||||
and decoding modes. In encoding mode, the callback is called once and
|
||||
should write out everything, including field tags. In decoding mode, the
|
||||
callback is called repeatedly for every data item.
|
||||
|
||||
To write more complex field callbacks, it is recommended to read the
|
||||
[Google Protobuf Encoding Specification](https://developers.google.com/protocol-buffers/docs/encoding).
|
||||
|
||||
### Encoding callbacks
|
||||
|
||||
bool (*encode)(pb_ostream_t *stream, const pb_field_iter_t *field, void * const *arg);
|
||||
|
||||
| | |
|
||||
| ---------- | ------------------------------------------------------------------ |
|
||||
| `stream` | Output stream to write to |
|
||||
| `field` | Iterator for the field currently being encoded or decoded. |
|
||||
| `arg` | Pointer to the `arg` field in the `pb_callback_t` structure. |
|
||||
|
||||
When encoding, the callback should write out complete fields, including
|
||||
the wire type and field number tag. It can write as many or as few
|
||||
fields as it likes. For example, if you want to write out an array as
|
||||
`repeated` field, you should do it all in a single call.
|
||||
|
||||
Usually you can use [pb_encode_tag_for_field](reference.html#pb-encode-tag-for-field) to
|
||||
encode the wire type and tag number of the field. However, if you want
|
||||
to encode a repeated field as a packed array, you must call
|
||||
[pb_encode_tag](reference.html#pb-encode-tag) instead to specify a
|
||||
wire type of `PB_WT_STRING`.
|
||||
|
||||
If the callback is used in a submessage, it will be called multiple
|
||||
times during a single call to [pb_encode](reference.html#pb-encode). In
|
||||
this case, it must produce the same amount of data every time. If the
|
||||
callback is directly in the main message, it is called only once.
|
||||
|
||||
This callback writes out a dynamically sized string:
|
||||
|
||||
bool write_string(pb_ostream_t *stream, const pb_field_iter_t *field, void * const *arg)
|
||||
{
|
||||
char *str = get_string_from_somewhere();
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
|
||||
return pb_encode_string(stream, (uint8_t*)str, strlen(str));
|
||||
}
|
||||
|
||||
### Decoding callbacks
|
||||
|
||||
bool (*decode)(pb_istream_t *stream, const pb_field_iter_t *field, void **arg);
|
||||
|
||||
| | |
|
||||
| ---------- | ------------------------------------------------------------------ |
|
||||
| `stream` | Input stream to read from |
|
||||
| `field` | Iterator for the field currently being encoded or decoded. |
|
||||
| `arg` | Pointer to the `arg` field in the `pb_callback_t` structure. |
|
||||
|
||||
When decoding, the callback receives a length-limited substring that
|
||||
reads the contents of a single field. The field tag has already been
|
||||
read. For `string` and `bytes`, the length value has already been
|
||||
parsed, and is available at `stream->bytes_left`.
|
||||
|
||||
The callback will be called multiple times for repeated fields. For
|
||||
packed fields, you can either read multiple values until the stream
|
||||
ends, or leave it to [pb_decode](reference.html#pb-decode) to call your
|
||||
function over and over until all values have been read.
|
||||
|
||||
This callback reads multiple integers and prints them:
|
||||
|
||||
bool read_ints(pb_istream_t *stream, const pb_field_iter_t *field, void **arg)
|
||||
{
|
||||
while (stream->bytes_left)
|
||||
{
|
||||
uint64_t value;
|
||||
if (!pb_decode_varint(stream, &value))
|
||||
return false;
|
||||
printf("%lld\n", value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
### Function name bound callbacks
|
||||
|
||||
bool MyMessage_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field);
|
||||
|
||||
| | |
|
||||
| ---------- | ------------------------------------------------------------------ |
|
||||
| `istream` | Input stream to read from, or NULL if called in encoding context. |
|
||||
| `ostream` | Output stream to write to, or NULL if called in decoding context. |
|
||||
| `field` | Iterator for the field currently being encoded or decoded. |
|
||||
|
||||
Storing function pointer in `pb_callback_t` fields inside
|
||||
the message requires extra storage space and is often cumbersome. As an
|
||||
alternative, the generator options `callback_function` and
|
||||
`callback_datatype` can be used to bind a callback function
|
||||
based on its name.
|
||||
|
||||
Typically this feature is used by setting
|
||||
`callback_datatype` to e.g. `void\*` or other
|
||||
data type used for callback state. Then the generator will automatically
|
||||
set `callback_function` to
|
||||
`MessageName_callback` and produce a prototype for it in
|
||||
generated `.pb.h`. By implementing this function in your own
|
||||
code, you will receive callbacks for fields without having to separately
|
||||
set function pointers.
|
||||
|
||||
If you want to use function name bound callbacks for some fields and
|
||||
`pb_callback_t` for other fields, you can call
|
||||
`pb_default_field_callback` from the message-level
|
||||
callback. It will then read a function pointer from
|
||||
`pb_callback_t` and call it.
|
||||
|
||||
## Message descriptor
|
||||
|
||||
For using the `pb_encode()` and `pb_decode()` functions, you need a
|
||||
description of all the fields contained in a message. This description
|
||||
is usually autogenerated from .proto file.
|
||||
|
||||
For example this submessage in the Person.proto file:
|
||||
|
||||
~~~~ protobuf
|
||||
message Person {
|
||||
message PhoneNumber {
|
||||
required string number = 1 [(nanopb).max_size = 40];
|
||||
optional PhoneType type = 2 [default = HOME];
|
||||
}
|
||||
}
|
||||
~~~~
|
||||
|
||||
This in turn generates a macro list in the `.pb.h` file:
|
||||
|
||||
#define Person_PhoneNumber_FIELDLIST(X, a) \
|
||||
X(a, STATIC, REQUIRED, STRING, number, 1) \
|
||||
X(a, STATIC, OPTIONAL, UENUM, type, 2)
|
||||
|
||||
Inside the `.pb.c` file there is a macro call to
|
||||
`PB_BIND`:
|
||||
|
||||
PB_BIND(Person_PhoneNumber, Person_PhoneNumber, AUTO)
|
||||
|
||||
These macros will in combination generate `pb_msgdesc_t`
|
||||
structure and associated lists:
|
||||
|
||||
const uint32_t Person_PhoneNumber_field_info[] = { ... };
|
||||
const pb_msgdesc_t * const Person_PhoneNumber_submsg_info[] = { ... };
|
||||
const pb_msgdesc_t Person_PhoneNumber_msg = {
|
||||
2,
|
||||
Person_PhoneNumber_field_info,
|
||||
Person_PhoneNumber_submsg_info,
|
||||
Person_PhoneNumber_DEFAULT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
The encoding and decoding functions take a pointer to this structure and
|
||||
use it to process each field in the message.
|
||||
|
||||
## Oneof
|
||||
|
||||
Protocol Buffers supports
|
||||
[oneof](https://developers.google.com/protocol-buffers/docs/reference/proto2-spec#oneof_and_oneof_field)
|
||||
sections, where only one of the fields contained within can be present. Here is an example of `oneof` usage:
|
||||
|
||||
~~~~ protobuf
|
||||
message MsgType1 {
|
||||
required int32 value = 1;
|
||||
}
|
||||
|
||||
message MsgType2 {
|
||||
required bool value = 1;
|
||||
}
|
||||
|
||||
message MsgType3 {
|
||||
required int32 value1 = 1;
|
||||
required int32 value2 = 2;
|
||||
}
|
||||
|
||||
message MyMessage {
|
||||
required uint32 uid = 1;
|
||||
required uint32 pid = 2;
|
||||
required uint32 utime = 3;
|
||||
|
||||
oneof payload {
|
||||
MsgType1 msg1 = 4;
|
||||
MsgType2 msg2 = 5;
|
||||
MsgType3 msg3 = 6;
|
||||
}
|
||||
}
|
||||
~~~~
|
||||
|
||||
Nanopb will generate `payload` as a C union and add an additional field
|
||||
`which_payload`:
|
||||
|
||||
typedef struct _MyMessage {
|
||||
uint32_t uid;
|
||||
uint32_t pid;
|
||||
uint32_t utime;
|
||||
pb_size_t which_payload;
|
||||
union {
|
||||
MsgType1 msg1;
|
||||
MsgType2 msg2;
|
||||
MsgType3 msg3;
|
||||
} payload;
|
||||
} MyMessage;
|
||||
|
||||
`which_payload` indicates which of the `oneof` fields is actually set.
|
||||
The user is expected to set the field manually using the correct field
|
||||
tag:
|
||||
|
||||
MyMessage msg = MyMessage_init_zero;
|
||||
msg.payload.msg2.value = true;
|
||||
msg.which_payload = MyMessage_msg2_tag;
|
||||
|
||||
Notice that neither `which_payload` field nor the unused fields in
|
||||
`payload` will consume any space in the resulting encoded message.
|
||||
|
||||
When a field inside `oneof` contains `pb_callback_t`
|
||||
fields, the callback values cannot be set before decoding. This is
|
||||
because the different fields share the same storage space in C
|
||||
`union`. Instead either function name bound callbacks or a
|
||||
separate message level callback can be used. See
|
||||
[tests/oneof_callback](https://github.com/nanopb/nanopb/tree/master/tests/oneof_callback)
|
||||
for an example on this.
|
||||
|
||||
## Extension fields
|
||||
|
||||
Protocol Buffers supports a concept of [extension
|
||||
fields](https://developers.google.com/protocol-buffers/docs/proto#extensions),
|
||||
which are additional fields to a message, but defined outside the actual
|
||||
message. The definition can even be in a completely separate .proto
|
||||
file.
|
||||
|
||||
The base message is declared as extensible by keyword `extensions` in
|
||||
the .proto file:
|
||||
|
||||
~~~~ protobuf
|
||||
message MyMessage {
|
||||
.. fields ..
|
||||
extensions 100 to 199;
|
||||
}
|
||||
~~~~
|
||||
|
||||
For each extensible message, `nanopb_generator.py` declares an
|
||||
additional callback field called `extensions`. The field and associated
|
||||
datatype `pb_extension_t` forms a linked list of handlers. When an
|
||||
unknown field is encountered, the decoder calls each handler in turn
|
||||
until either one of them handles the field, or the list is exhausted.
|
||||
|
||||
The actual extensions are declared using the `extend` keyword in the
|
||||
.proto, and are in the global namespace:
|
||||
|
||||
~~~~ protobuf
|
||||
extend MyMessage {
|
||||
optional int32 myextension = 100;
|
||||
}
|
||||
~~~~
|
||||
|
||||
For each extension, `nanopb_generator.py` creates a constant of type
|
||||
`pb_extension_type_t`. To link together the base message and the
|
||||
extension, you have to:
|
||||
|
||||
1. Allocate storage for your field, matching the datatype in the
|
||||
.proto. For example, for a `int32` field, you need a `int32_t`
|
||||
variable to store the value.
|
||||
2. Create a `pb_extension_t` constant, with pointers to your variable
|
||||
and to the generated `pb_extension_type_t`.
|
||||
3. Set the `message.extensions` pointer to point to the
|
||||
`pb_extension_t`.
|
||||
|
||||
An example of this is available in `tests/test_encode_extensions.c`
|
||||
and `tests/test_decode_extensions.c`.
|
||||
|
||||
## Default values
|
||||
|
||||
Protobuf has two syntax variants, proto2 and proto3. Of these proto2 has
|
||||
user definable default values that can be given in .proto file:
|
||||
|
||||
~~~~ protobuf
|
||||
message MyMessage {
|
||||
optional bytes foo = 1 [default = "ABC\x01\x02\x03"];
|
||||
optional string bar = 2 [default = "åäö"];
|
||||
}
|
||||
~~~~
|
||||
|
||||
Nanopb will generate both static and runtime initialization for the
|
||||
default values. In `myproto.pb.h` there will be a
|
||||
`#define MyMessage_init_default {...}` that can be used to initialize
|
||||
whole message into default values:
|
||||
|
||||
MyMessage msg = MyMessage_init_default;
|
||||
|
||||
In addition to this, `pb_decode()` will initialize message
|
||||
fields to defaults at runtime. If this is not desired,
|
||||
`pb_decode_ex()` can be used instead.
|
||||
|
||||
## Message framing
|
||||
|
||||
Protocol Buffers does not specify a method of framing the messages for
|
||||
transmission. This is something that must be provided by the library
|
||||
user, as there is no one-size-fits-all solution. Typical needs for a
|
||||
framing format are to:
|
||||
|
||||
1. Encode the message length.
|
||||
2. Encode the message type.
|
||||
3. Perform any synchronization and error checking that may be needed
|
||||
depending on application.
|
||||
|
||||
For example UDP packets already fulfill all the requirements, and TCP
|
||||
streams typically only need a way to identify the message length and
|
||||
type. Lower level interfaces such as serial ports may need a more robust
|
||||
frame format, such as HDLC (high-level data link control).
|
||||
|
||||
Nanopb provides a few helpers to facilitate implementing framing
|
||||
formats:
|
||||
|
||||
1. Functions `pb_encode_ex` and `pb_decode_ex` prefix the message
|
||||
data with a varint-encoded length.
|
||||
2. Union messages and oneofs are supported in order to implement
|
||||
top-level container messages.
|
||||
3. Message IDs can be specified using the `(nanopb_msgopt).msgid`
|
||||
option and can then be accessed from the header.
|
||||
|
||||
## Return values and error handling
|
||||
|
||||
Most functions in nanopb return bool: `true` means success, `false`
|
||||
means failure. There is also support for error messages for
|
||||
debugging purposes: the error messages go in `stream->errmsg`.
|
||||
|
||||
The error messages help in guessing what is the underlying cause of the
|
||||
error. The most common error conditions are:
|
||||
|
||||
1) Invalid protocol buffers binary message.
|
||||
2) Mismatch between binary message and .proto message type.
|
||||
3) Unterminated message (incorrect message length).
|
||||
4) Exceeding the max_size or bytes_left of a stream.
|
||||
5) Exceeding the max_size/max_count of a string or array field
|
||||
6) IO errors in your own stream callbacks.
|
||||
7) Errors that happen in your callback functions.
|
||||
8) Running out of memory, i.e. stack overflow.
|
||||
9) Invalid field descriptors (would usually mean a bug in the generator).
|
||||
|
||||
## Static assertions
|
||||
|
||||
Nanopb code uses static assertions to check size of structures at the compile
|
||||
time. The `PB_STATIC_ASSERT` macro is defined in `pb.h`. If ISO C11 standard
|
||||
is available, the C standard `_Static_assert` keyword is used, otherwise a
|
||||
negative sized array definition trick is used.
|
||||
|
||||
Common reasons for static assertion errors are:
|
||||
|
||||
1. `FIELDINFO_DOES_NOT_FIT_width2` with `width1` or `width2`:
|
||||
Message that is larger than 256 bytes, but nanopb generator does not detect
|
||||
it for some reason. Often resolved by giving all `.proto` files as argument
|
||||
to `nanopb_generator.py` at the same time, to ensure submessage definitions
|
||||
are found. Alternatively `(nanopb).descriptorsize = DS_4` option can be
|
||||
given manually.
|
||||
|
||||
2. `FIELDINFO_DOES_NOT_FIT_width4` with `width4`:
|
||||
Message that is larger than 64 kilobytes. There will be a better error
|
||||
message for this in a future nanopb version, but currently it asserts here.
|
||||
The compile time option `PB_FIELD_32BIT` should be specified either on
|
||||
C compiler command line or by editing `pb.h`. This will increase the sizes
|
||||
of integer types used internally in nanopb code.
|
||||
|
||||
3. `DOUBLE_MUST_BE_8_BYTES`:
|
||||
Some platforms, most notably AVR, do not support the 64-bit `double` type,
|
||||
only 32-bit `float`. The compile time option `PB_CONVERT_DOUBLE_FLOAT` can
|
||||
be defined to convert between the types automatically. The conversion
|
||||
results in small rounding errors and takes unnecessary space in transmission,
|
||||
so changing the `.proto` to use `float` type is often better.
|
||||
|
||||
4. `INT64_T_WRONG_SIZE`:
|
||||
The `stdint.h` system header is incorrect for the C compiler being used.
|
||||
This can result from erroneous compiler include path.
|
||||
If the compiler actually does not support 64-bit types, the compile time
|
||||
option `PB_WITHOUT_64BIT` can be used.
|
||||
|
||||
5. `variably modified array size`:
|
||||
The compiler used has problems resolving the array-based static assert at
|
||||
compile time. Try setting the compiler to C11 standard mode if possible.
|
||||
If static assertions cannot be made to work on the compiler used, the
|
||||
compile-time option `PB_NO_STATIC_ASSERT` can be specified to turn them off.
|
2869
third_party/nanopb/docs/generator_flow.svg
vendored
Normal file
2869
third_party/nanopb/docs/generator_flow.svg
vendored
Normal file
File diff suppressed because it is too large
Load diff
After Width: | Height: | Size: 112 KiB |
158
third_party/nanopb/docs/index.md
vendored
Normal file
158
third_party/nanopb/docs/index.md
vendored
Normal file
|
@ -0,0 +1,158 @@
|
|||
# Nanopb: Overview
|
||||
|
||||
Nanopb is an ANSI-C library for encoding and decoding messages in
|
||||
Google's [Protocol Buffers](https://developers.google.com/protocol-buffers/docs/reference/overview)
|
||||
format with minimal requirements for RAM and code space. It is primarily
|
||||
suitable for 32-bit microcontrollers.
|
||||
|
||||
Documentation version
|
||||
---------------------
|
||||
|
||||
This documentation applies for nanopb 0.4.0 and later versions. For
|
||||
documentation of older releases,
|
||||
[see here](https://github.com/nanopb/nanopb/blob/maintenance_0.3/docs/index.rst).
|
||||
|
||||
Overall structure
|
||||
-----------------
|
||||
|
||||
For the runtime program, you always need `pb.h` for type declarations
|
||||
and `pb_common.h/c` for base functions. Depending on whether you want
|
||||
to encode, decode, or both, you also need `pb_encode.h/c` or
|
||||
`pb_decode.h/c`.
|
||||
|
||||
The high-level encoding and decoding functions take a pointer to
|
||||
`pb_msgdesc_t` structure, which describes the fields of a message
|
||||
structure. Usually you want these autogenerated from a `.proto` file.
|
||||
The tool script `nanopb_generator.py` accomplishes this.
|
||||
|
||||

|
||||
|
||||
So a typical project might include these files:
|
||||
|
||||
1. Nanopb runtime library:
|
||||
- pb.h
|
||||
- pb_common.h and pb_common.c (always needed)
|
||||
- pb_decode.h and pb_decode.c (needed for decoding messages)
|
||||
- pb_encode.h and pb_encode.c (needed for encoding messages)
|
||||
|
||||
2. Protocol description (you can have many):
|
||||
- person.proto (just an example)
|
||||
- person.pb.c (autogenerated, contains message descriptors)
|
||||
- person.pb.h (autogenerated, contains type declarations and macros)
|
||||
|
||||
Features and limitations
|
||||
------------------------
|
||||
|
||||
**Features**
|
||||
|
||||
1) Pure C runtime
|
||||
2) Small code size (5--10 kB depending on processor and compilation options, plus any message definitions)
|
||||
3) Small ram usage (typically \~300 bytes stack, plus any message structs)
|
||||
4) Allows specifying maximum size for strings and arrays, so that they can be allocated statically.
|
||||
5) No malloc needed: everything can be allocated statically or on the stack. Optional malloc support available.
|
||||
6) You can use either encoder or decoder alone to cut the code size in half.
|
||||
7) Support for most protobuf features, including: all data types,
|
||||
nested submessages, default values, repeated and optional fields,
|
||||
oneofs, packed arrays, extension fields.
|
||||
8) Callback mechanism for handling messages larger than can fit in available RAM.
|
||||
9) Extensive set of tests.
|
||||
|
||||
**Limitations**
|
||||
|
||||
1) Some speed has been sacrificed for code size.
|
||||
2) Encoding is focused on writing to streams. For memory buffers only it could be made more efficient.
|
||||
3) The deprecated Protocol Buffers feature called "groups" is not supported.
|
||||
4) Fields in the generated structs are ordered by the tag number, instead of the natural ordering in .proto file.
|
||||
5) Unknown fields are not preserved when decoding and re-encoding a message.
|
||||
6) Reflection (runtime introspection) is not supported. E.g. you can't request a field by giving its name in a string.
|
||||
7) Numeric arrays are always encoded as packed, even if not marked as packed in .proto.
|
||||
8) Cyclic references between messages are supported only in callback and malloc mode.
|
||||
9) Nanopb doesn't have a stable ABI (application binary interface)
|
||||
between versions, so using it as a shared library (.so / .dll)
|
||||
requires extra care.
|
||||
|
||||
Getting started
|
||||
---------------
|
||||
|
||||
For starters, consider this simple message:
|
||||
|
||||
~~~~ protobuf
|
||||
message Example {
|
||||
required int32 value = 1;
|
||||
}
|
||||
~~~~
|
||||
|
||||
Save this in `message.proto` and compile it:
|
||||
|
||||
user@host:~$ python nanopb/generator/nanopb_generator.py message.proto
|
||||
|
||||
You should now have in `message.pb.h`:
|
||||
|
||||
typedef struct {
|
||||
int32_t value;
|
||||
} Example;
|
||||
|
||||
extern const pb_msgdesc_t Example_msg;
|
||||
#define Example_fields &Example_msg
|
||||
|
||||
Then you have to include the nanopb headers and the generated header:
|
||||
|
||||
#include <pb_encode.h>
|
||||
#include "message.pb.h"
|
||||
|
||||
Now in your main program do this to encode a message:
|
||||
|
||||
Example mymessage = {42};
|
||||
uint8_t buffer[10];
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
pb_encode(&stream, Example_fields, &mymessage);
|
||||
|
||||
After that, buffer will contain the encoded message. The number of bytes
|
||||
in the message is stored in `stream.bytes_written`. You can feed the
|
||||
message to `protoc --decode=Example message.proto` to verify its
|
||||
validity.
|
||||
|
||||
For a complete example of the simple case, see [examples/simple/simple.c](https://github.com/nanopb/nanopb/blob/master/examples/simple/simple.c).
|
||||
For a more complex example with network interface, see the [examples/network_server](https://github.com/nanopb/nanopb/tree/master/examples/network_server) subdirectory.
|
||||
|
||||
Compiler requirements
|
||||
---------------------
|
||||
|
||||
Nanopb should compile with most ansi-C compatible compilers. It however
|
||||
requires a few header files to be available:
|
||||
|
||||
1) `string.h`, with these functions: `strlen`, `memcpy`, `memset`
|
||||
2) `stdint.h`, for definitions of `int32_t` etc.
|
||||
3) `stddef.h`, for definition of `size_t`
|
||||
4) `stdbool.h`, for definition of `bool`
|
||||
5) `limits.h`, for definition of `CHAR_BIT`
|
||||
|
||||
If these header files do not come with your compiler, you can use the
|
||||
file `extra/pb_syshdr.h` instead. It contains an example of how to
|
||||
provide the dependencies. You may have to edit it a bit to suit your
|
||||
custom platform.
|
||||
|
||||
To use the pb_syshdr.h, define `PB_SYSTEM_HEADER` as
|
||||
`"pb_syshdr.h"` (including the quotes). Similarly, you can provide a
|
||||
custom include file, which should provide all the dependencies listed
|
||||
above.
|
||||
|
||||
Running the test cases
|
||||
----------------------
|
||||
|
||||
Extensive unittests and test cases are included under the `tests`
|
||||
folder.
|
||||
|
||||
To build the tests, you will need the [scons](http://www.scons.org/)
|
||||
build system. The tests should be runnable on most platforms. Windows
|
||||
and Linux builds are regularly tested. The tests also support embedded
|
||||
targets: STM32 (ARM Cortex-M) and AVR builds are regularly tested.
|
||||
|
||||
In addition to the build system, you will also need a working Google
|
||||
Protocol Buffers `protoc` compiler, and the Python bindings for Protocol
|
||||
Buffers.
|
||||
|
||||
Easiest way to install dependencies is to use the Python package manager
|
||||
[pip](https://pypi.org/project/pip/), which works on all platforms supported by Python:
|
||||
|
||||
pip3 install scons protobuf grpcio-tools
|
BIN
third_party/nanopb/docs/logo/logo.png
vendored
Normal file
BIN
third_party/nanopb/docs/logo/logo.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
1470
third_party/nanopb/docs/logo/logo.svg
vendored
Normal file
1470
third_party/nanopb/docs/logo/logo.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 102 KiB |
BIN
third_party/nanopb/docs/logo/logo16px.png
vendored
Normal file
BIN
third_party/nanopb/docs/logo/logo16px.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 854 B |
BIN
third_party/nanopb/docs/logo/logo48px.png
vendored
Normal file
BIN
third_party/nanopb/docs/logo/logo48px.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
233
third_party/nanopb/docs/lsr.css
vendored
Normal file
233
third_party/nanopb/docs/lsr.css
vendored
Normal file
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
Original author: Peter Parente
|
||||
Date: 2008/01/22
|
||||
Version: 1.0 (modified)
|
||||
Copyright: This stylesheet has been placed in the public domain - free to edit and use for all uses.
|
||||
|
||||
--
|
||||
|
||||
Heavily modified for use in nanopb documentation.
|
||||
2011-2020 Petteri Aimonen
|
||||
*/
|
||||
|
||||
body {
|
||||
font: 100% sans-serif;
|
||||
background: #ffffff;
|
||||
color: black;
|
||||
margin: 2em;
|
||||
padding: 0em 2em;
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
p.topic-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table.docinfo {
|
||||
text-align: left;
|
||||
margin: 2em 0em;
|
||||
}
|
||||
|
||||
a[href] {
|
||||
color: #436976;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h1 a[href] {
|
||||
color: #003a6b;
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
a.strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img {
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 3px solid black;
|
||||
background-color: #f6f6f6;
|
||||
padding: 0.5em 1em 0.2em 1em;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0.5em 0 1em 0;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
p a:visited {
|
||||
color: purple;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
p a:active {
|
||||
color: red;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
p img {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
p.rubric {
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
em, cite {
|
||||
font-style: normal;
|
||||
font-family: monospace;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre {
|
||||
border-left: 3px double #aaa;
|
||||
padding: 5px 10px;
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
|
||||
code {
|
||||
border: 1px solid rgba(128, 128, 128, 0.1);
|
||||
padding: 1px 5px;
|
||||
border-radius: 5px;
|
||||
background-color: rgba(128, 128, 128, 0.05);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
pre code {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: #000;
|
||||
background-color: transparent;
|
||||
margin: 0em;
|
||||
padding-top: 0.5em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #003a6b;
|
||||
font-size: 180%;
|
||||
margin-bottom: 0.5em;
|
||||
border-bottom: 2px solid #aaa;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #003a6b;
|
||||
font-size: 130%;
|
||||
margin-bottom: 0.5em;
|
||||
border-bottom: 1px solid #aaa;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 120%;
|
||||
margin-bottom: 0.5em;
|
||||
margin-top: 1.0em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 110%;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.5em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 105%;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 100%;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
table {
|
||||
text-align: left;
|
||||
border-collapse: collapse;
|
||||
margin: 1.5em 0em;
|
||||
}
|
||||
|
||||
table td, table th {
|
||||
padding: 0.25em 1em;
|
||||
border-top: 1px solid gray;
|
||||
border-bottom: 1px solid gray;
|
||||
}
|
||||
|
||||
#index {
|
||||
margin: 2em 2em 2em 0em;
|
||||
padding: 0em 1em;
|
||||
border-top: 1px solid #aaa;
|
||||
border-left: 1px solid #aaa;
|
||||
border-bottom: 2px solid #555;
|
||||
border-right: 2px solid #555;
|
||||
max-width: 20em;
|
||||
}
|
||||
|
||||
#index h2 {
|
||||
margin-bottom: 0em;
|
||||
margin-top: 0em;
|
||||
color: #003a6b;
|
||||
font-size: 100%;
|
||||
border-bottom: 1px solid #aaa;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#feedback_link {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#feedback {
|
||||
visibility: hidden;
|
||||
padding: 1em;
|
||||
border-radius: 5px;
|
||||
position: fixed;
|
||||
top: 10em;
|
||||
right: 10em;
|
||||
background: white;
|
||||
border-top: 1px solid #aaa;
|
||||
border-left: 1px solid #aaa;
|
||||
border-bottom: 2px solid #555;
|
||||
border-right: 2px solid #555;
|
||||
}
|
||||
|
||||
#feedback:target {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#feedback .cancel {
|
||||
color: #666;
|
||||
padding-left: 2em;
|
||||
}
|
648
third_party/nanopb/docs/migration.md
vendored
Normal file
648
third_party/nanopb/docs/migration.md
vendored
Normal file
|
@ -0,0 +1,648 @@
|
|||
# Nanopb: Migration from older versions
|
||||
|
||||
This document details all the breaking changes that have been made to
|
||||
nanopb since its initial release. For each change, the rationale and
|
||||
required modifications of user applications are explained. Also any
|
||||
error indications are included, in order to make it easier to find this
|
||||
document.
|
||||
|
||||
Nanopb-0.4.6 (2022-05-30)
|
||||
-------------------------
|
||||
|
||||
### NANOPB_VERSION define is now a string
|
||||
|
||||
**Changes:** To ease `NANOPB_VERSION` macro usage, the value is directly a string.
|
||||
|
||||
**Required actions:** Most nanopb users probably never used that macro. If so,
|
||||
you certainly use the `#` preprocessor to convert it as string. You, now,
|
||||
only have to call it directly, like this for example:
|
||||
`strcpy(myvar, NANOPB_VERSION);`
|
||||
|
||||
### FindNanopb.cmake now requires protoc 3.6.0 or newer by default
|
||||
|
||||
**Changes:** The default options passing method now uses `--plugin-opt` which
|
||||
is supported by protoc 3.6.0 and newer (released in 2018).
|
||||
|
||||
**Required actions:** Update `protoc` if needed, or alternatively install
|
||||
`grpcio-tools` package from `pip`. If neither is possible, the
|
||||
`NANOPB_PROTOC_OLDER_THAN_3_6_0` cmake option can be used to restore the old
|
||||
style option passing. Note that it has problems with special characters such
|
||||
as `:`.
|
||||
|
||||
**Error indications:** "`protoc: Unknown flag: --nanopb_opt`"
|
||||
|
||||
### pb.h uses C11 _Static_assert keyword by default
|
||||
|
||||
**Rationale:** The nanopb generated headers use static assertions to catch
|
||||
errors at compile time. There are several mechanisms to implement this.
|
||||
The most widely supported is C11 `_Static_assert` keyword.
|
||||
Previously the code used negative size array definition trick, which is
|
||||
supported already in C99 but does not work with every compiler and can
|
||||
produce confusing error messages.
|
||||
|
||||
**Changes:** Now `_Static_assert` is used by default.
|
||||
|
||||
**Required actions:** If the keyword is not recognized, set the compiler to
|
||||
C11 standard mode if available. If it is not available, define either `PB_C99_STATIC_ASSERT`
|
||||
or `PB_NO_STATIC_ASSERT` in `pb.h` or on compiler command line.
|
||||
|
||||
**Error indications:** `Undefined identifier _Static_assert`
|
||||
|
||||
Nanopb-0.4.4 (2020-11-25)
|
||||
-------------------------
|
||||
|
||||
### Remove outdated generator/nanopb/options.proto
|
||||
|
||||
**Changes:** Back in 2018, it was considered in pull request #241 to
|
||||
move nanopb generator options to a separate namespace. For this reason,
|
||||
a transitional file was added. It was later abandoned and is now removed
|
||||
to avoid confusion.
|
||||
|
||||
**Required actions:** Most nanopb users probably never used that transitional
|
||||
file at all. If your `.proto` files import it, change to using `generator/proto/nanopb.proto`.
|
||||
|
||||
**Error indications:** Errors about missing file `options.proto` when running
|
||||
the generator.
|
||||
|
||||
Nanopb-0.4.3 (2020-09-21)
|
||||
-------------------------
|
||||
|
||||
### pb_msgdesc_t struct has new fields
|
||||
|
||||
**Changes:** New fields `required_field_count` and
|
||||
`largest_tag` were added to `pb_msgdesc_t`
|
||||
and existing fields were reordered.
|
||||
|
||||
**Required actions:** All `.pb.c` files must be recompiled.
|
||||
Regeneration is not needed.
|
||||
|
||||
**Error indications:** Messages may fail to encode or decode, or the
|
||||
code can crash inside `load_descriptor_values()` in
|
||||
`pb_common.c`.
|
||||
|
||||
Nanopb-0.4.2 (2020-06-23)
|
||||
-------------------------
|
||||
|
||||
### Generator now uses Python 3 by default
|
||||
|
||||
**Rationale:** Previously `nanopb-generator.py` had hashbang
|
||||
of `#!/usr/bin/env python`, which would execute with Python
|
||||
2 on most systems. Python 2 is now deprecated and many libraries are
|
||||
dropping support for it, which makes installing dependencies difficult.
|
||||
While `nanopb_generator.py` has worked with Python 3 for
|
||||
years now, and overriding the python version was possible with
|
||||
virtualenv, that was an extra complication.
|
||||
|
||||
**Changes:** Hashbang now uses `#!/usr/bin/env python3`.
|
||||
New file `nanopb_generator.py2` can be used to run with
|
||||
Python 2, if necessary.
|
||||
|
||||
**Required actions:** If possible, just verify Python 3 is installed and
|
||||
necessary dependencies are installed for it. For example `pip3 install protobuf grpcio-tools`
|
||||
should take care of it. If this is not possible, call `nanopb_generator.py2` from your build
|
||||
scripts instead.
|
||||
|
||||
**Error indications:** `python3: command not found` if
|
||||
Python 3 is not installed.
|
||||
`Could not import the Google protobuf Python libraries` if dependencies are only installed for Python 2.
|
||||
|
||||
Nanopb-0.4.0 (2019-12-20)
|
||||
-------------------------
|
||||
|
||||
### New field descriptor format
|
||||
|
||||
**Rationale:** Previously information about struct fields was stored as
|
||||
an array of `pb_field_t` structures. This was a
|
||||
straightforward method, but required allocating space for e.g.
|
||||
submessage type and array size for all fields, even though most fields
|
||||
are not submessages nor arrays.
|
||||
|
||||
**Changes:** Now field information is encoded more efficiently in
|
||||
`uint32_t` array in a variable-length format. Old
|
||||
`pb_field_t` structure has been removed and it is now a
|
||||
typedef for `pb_field_iter_t`. This retains compatibility
|
||||
with most old callback definitions. The field definitions in
|
||||
`.pb.h` files are now of type `pb_msgdesc_t`.
|
||||
|
||||
**Required actions:** If your own code accesses the low-level field
|
||||
information in `pb_field_t`, it must be modified to do so
|
||||
only through the functions declared in `pb_common.h`.
|
||||
|
||||
**Error indications:** `incompatible pointer type` errors
|
||||
relating to `pb_field_t`
|
||||
|
||||
### Changes to generator default options
|
||||
|
||||
**Rationale:** Previously nanopb_generator added a timestamp header to
|
||||
generated files and used only basename of files in
|
||||
`#include` directives. This is different than what the
|
||||
`protoc` C++ backend does.
|
||||
|
||||
**Changes:** Now default options are `--no-timestamp` and
|
||||
`--no-strip-path`.
|
||||
|
||||
**Required actions:** If old behaviour is desired, add
|
||||
`--timestamp` and `--strip-path` options to
|
||||
`nanopb_generator.py` or on `protoc` command
|
||||
line as `--nanopb_out=--timestamp,--strip-path:outdir`.
|
||||
|
||||
**Error indications:** Compiler error: cannot find include file
|
||||
`mymessage.pb.h` when compiling
|
||||
`mymessage.pb.c`.
|
||||
|
||||
### Removal of bundled plugin.proto
|
||||
|
||||
**Rationale:** Google's Python protobuf library, which is used in
|
||||
nanopb generator, has included `plugin_pb2` with it since
|
||||
version 3.1.0. It is not necessary to bundle it with nanopb anymore.
|
||||
|
||||
**Required actions:** Update `python-protobuf` to version
|
||||
3.1.0 or newer.
|
||||
|
||||
**Error indications:** `ImportError: No module named compiler.plugin_pb2`
|
||||
|
||||
### .options file is now always case-sensitive
|
||||
|
||||
**Rationale:** Previously field names in `.options` file
|
||||
were case-sensitive on Linux and case-insensitive on Windows. This was
|
||||
by accident. Because `.proto` files are case-sensitive,
|
||||
`.options` files should be too.
|
||||
|
||||
**Changes:** Now field names in `.options` are always
|
||||
case-sensitive, and matched by `fnmatchcase()` instead of
|
||||
`fnmatch()`.
|
||||
|
||||
**Required actions:** If field names in `.options` are not
|
||||
capitalized the same as in `.proto`, they must be updated.
|
||||
|
||||
### `CHAR_BIT` define is now needed
|
||||
|
||||
**Rationale:** To check whether the platform has 8-bit or larger chars,
|
||||
the C standard `CHAR_BIT` macro is needed.
|
||||
|
||||
**Changes:** `pb.h` now includes `limits.h` for this macro.
|
||||
|
||||
**Required actions:** If your platform doesn't have `limits.h`
|
||||
available, you can define the macro in `pb_syshdr.h`. There is an
|
||||
example in `extra` directory.
|
||||
|
||||
**Error indications:** `"Cannot find include file <limits.h>."` or
|
||||
`"Undefined identifier: CHAR_BIT."`
|
||||
|
||||
### Strings must now always be null-terminated
|
||||
|
||||
**Rationale:** Previously `pb_encode()` would accept non-terminated
|
||||
strings and assume that they are the full length of the defined array.
|
||||
However, `pb_decode()` would reject such messages because null
|
||||
terminator wouldn't fit in the array.
|
||||
|
||||
**Changes:** `pb_encode()` will now return an error if null terminator
|
||||
is missing. Maximum encoded message size calculation is changed
|
||||
accordingly so that at most `max_size-1` strings are assumed. New field
|
||||
option `max_length` can be used to define the maximum string length,
|
||||
instead of the array size.
|
||||
|
||||
**Required actions:** If your strings were previously filling the whole
|
||||
allocated array, increase the size of the field by 1.
|
||||
|
||||
**Error indications:** `pb_encode()` returns error `unterminated string`.
|
||||
|
||||
### Removal of per-field default value constants
|
||||
|
||||
**Rationale:** Previously nanopb declared a
|
||||
`fieldname_default` constant variable for each field with a
|
||||
default value, and used these internally to initialize messages. This
|
||||
however used unnecessarily large amount of storage for the values. The
|
||||
variables were mostly for internal usage, but were available in the
|
||||
header file.
|
||||
|
||||
**Changes:** Default values are now stored as an encoded protobuf
|
||||
message.
|
||||
|
||||
**Required actions:** If your code previously used default constants, it
|
||||
will have to be adapted to take the default value in some other way,
|
||||
such as by defining
|
||||
`static const MyMessage msg_default = MyMessage_init_default;` and accessing
|
||||
`msg_default.fieldname`.
|
||||
|
||||
**Error indications:** Compiler error about `fieldname_default` being undeclared.
|
||||
|
||||
### Zero tag in message now raises error by default
|
||||
|
||||
**Rationale:** Previously nanopb has allowed messages to be terminated
|
||||
by a null byte, which is read as zero tag value. Most other protobuf
|
||||
implementations don't support this, so it is not very useful feature.
|
||||
It has also been noted that this can complicate debugging issues with
|
||||
corrupted messages.
|
||||
|
||||
**Changes:** `pb_decode()` now gives error when it
|
||||
encounters zero tag value. A new function `pb_decode_ex()`
|
||||
supports flag `PB_DECODE_NULLTERMINATED` that supports
|
||||
decoding null terminated messages.
|
||||
|
||||
**Required actions:** If application uses null termination for messages,
|
||||
switch it to use `pb_decode_ex()` and
|
||||
`pb_encode_ex()`. If compatibility with 0.3.9.x is needed,
|
||||
there are also `pb_decode_nullterminated()` and
|
||||
`pb_encode_nullterminated()` macros, which work both in
|
||||
0.4.0 and 0.3.9.
|
||||
|
||||
**Error indications:** Error message from `pb_decode()`: `zero_tag`.
|
||||
|
||||
### Submessages now have has_field in proto3 mode
|
||||
|
||||
**Rationale:** Previously nanopb considered proto3 submessages as
|
||||
present only when their contents was non-zero. Most other protobuf
|
||||
libraries allow explicit null state for submessages.
|
||||
|
||||
**Changes:** Submessages now have separate `has_field` in
|
||||
proto3 mode also.
|
||||
|
||||
**Required actions:** When using submessages in proto3 mode, user code
|
||||
must now set `mymsg.has_submsg = true` for each submessage
|
||||
that is present. Alternatively, the field option
|
||||
`proto3_singular_msgs` can be used to restore the old
|
||||
behavior.
|
||||
|
||||
**Error indications:** Submessages do not get encoded.
|
||||
|
||||
### PB_OLD_CALLBACK_STYLE option has been removed
|
||||
|
||||
**Rationale:** Back in 2013, function signature for callbacks was
|
||||
changed. The `PB_OLD_CALLBACK_STYLE` option allowed
|
||||
compatibility with old code, but complicated code and testing because of
|
||||
the different options.
|
||||
|
||||
**Changes:** `PB_OLD_CALLBACK_STYLE` option no-longer has
|
||||
any effect.
|
||||
|
||||
**Required actions:** If `PB_OLD_CALLBACK_STYLE` option
|
||||
was in use previously, function signatures must be updated to use double
|
||||
pointers (`void**` and `void * const *`).
|
||||
|
||||
**Error indications:** Assignment from incompatible pointer type.
|
||||
|
||||
### protoc insertion points are no longer included by default
|
||||
|
||||
**Rationale:** Protoc allows including comments in form
|
||||
`@@protoc_insertion_point` to identify locations for
|
||||
other plugins to insert their own extra content. Previously these were
|
||||
included by default, but they clutter the generated files and are rarely
|
||||
used.
|
||||
|
||||
**Changes:** Insertion points are now included only when
|
||||
`--protoc-insertion-points` option is passed to the
|
||||
generator.
|
||||
|
||||
Nanopb-0.3.9.4, 0.4.0 (2019-10-13)
|
||||
----------------------------------
|
||||
|
||||
### Fix generation of min/max defines for enum types
|
||||
|
||||
**Rationale:** Nanopb generator makes \#defines for enum minimum and
|
||||
maximum value. Previously these defines incorrectly had the first and
|
||||
last enum value, instead of the actual minimum and maximum. (issue
|
||||
#405)
|
||||
|
||||
**Changes:** Minimum define now always has the smallest value, and
|
||||
maximum define always has the largest value.
|
||||
|
||||
**Required actions:** If these defines are used and enum values in
|
||||
.proto file are not defined in ascending order, user code behaviour may
|
||||
change. Check that user code doesn\'t expect the old, incorrect
|
||||
first/last behaviour.
|
||||
|
||||
### Fix undefined behavior related to bool fields
|
||||
|
||||
**Rationale:** In C99, `bool` variables are not allowed to
|
||||
have other values than `true` and `false`.
|
||||
Compilers use this fact in optimization, and constructs like
|
||||
`int foo = msg.has_field ? 100 : 0;` will give unexpected results
|
||||
otherwise. Previously nanopb didn\'t enforce that decoded bool fields
|
||||
had valid values.
|
||||
|
||||
**Changes:** Bool fields are now handled separately as
|
||||
`PB_LTYPE_BOOL`. The `LTYPE` descriptor
|
||||
numbers for other field types were renumbered.
|
||||
|
||||
**Required actions:** Source code files must be recompiled, but
|
||||
regenerating `.pb.h`/`.pb.c` files from
|
||||
`.proto` is not required. If user code directly uses the
|
||||
nanopb internal field representation (search for
|
||||
`PB_LTYPE_VARINT` in source), it may need updating.
|
||||
|
||||
Nanopb-0.3.9.1, 0.4.0 (2018-04-14)
|
||||
----------------------------------
|
||||
|
||||
### Fix handling of string and bytes default values
|
||||
|
||||
**Rationale:** Previously nanopb didn't properly decode special
|
||||
character escapes like `\200` emitted by protoc. This caused these
|
||||
escapes to end up verbatim in the default values in .pb.c file.
|
||||
|
||||
**Changes:** Escapes are now decoded, and e.g. `\200` or `\x80`
|
||||
results in {0x80} for bytes field and `"\x80"` for string field.
|
||||
|
||||
**Required actions:** If code has previously relied on `\` in default
|
||||
value being passed through verbatim, it must now be changed to `\\`.
|
||||
|
||||
Nanopb-0.3.8 (2017-03-05)
|
||||
-------------------------
|
||||
|
||||
### Fully drain substreams before closing
|
||||
|
||||
**Rationale:** If the substream functions were called directly and the
|
||||
caller did not completely empty the substring before closing it, the
|
||||
parent stream would be put into an incorrect state.
|
||||
|
||||
**Changes:** `pb_close_string_substream` can now error and returns a
|
||||
boolean.
|
||||
|
||||
**Required actions:** Add error checking onto any call to
|
||||
`pb_close_string_substream`.
|
||||
|
||||
### Change oneof format in .pb.c files
|
||||
|
||||
**Rationale:** Previously two oneofs in a single message would be
|
||||
erroneously handled as part of the same union.
|
||||
|
||||
**Changes:** Oneofs fields now use special `PB_DATAOFFSET_UNION`
|
||||
offset type in generated .pb.c files to distinguish whether they are the
|
||||
first or following field inside an union.
|
||||
|
||||
**Required actions:** Regenerate `.pb.c/.pb.h` files with new nanopb
|
||||
version if oneofs are used.
|
||||
|
||||
Nanopb-0.3.5 (2016-02-13)
|
||||
-------------------------
|
||||
|
||||
### Add support for platforms without uint8_t
|
||||
|
||||
**Rationale:** Some platforms cannot access 8-bit sized values directly,
|
||||
and do not define `uint8_t`. Nanopb previously didn\'t support these
|
||||
platforms.
|
||||
|
||||
**Changes:** References to `uint8_t` were replaced with several
|
||||
alternatives, one of them being a new `pb_byte_t` typedef. This in
|
||||
turn uses `uint_least8_t` which means the smallest available type.
|
||||
|
||||
**Required actions:** If your platform does not have a
|
||||
standards-compliant `stdint.h`, it may lack the definition for
|
||||
`[u]int_least8_t`. This must be added manually, example can be found
|
||||
in `extra/pb_syshdr.h`.
|
||||
|
||||
**Error indications:** Compiler error: `"unknown type name 'uint_least8_t'"`.
|
||||
|
||||
Nanopb-0.3.2 (2015-01-24)
|
||||
-------------------------
|
||||
|
||||
### Add support for OneOfs
|
||||
|
||||
**Rationale:** Previously nanopb did not support the `oneof` construct
|
||||
in `.proto` files. Those fields were generated as regular `optional`
|
||||
fields.
|
||||
|
||||
**Changes:** OneOfs are now generated as C unions. Callback fields are
|
||||
not supported inside oneof and generator gives an error.
|
||||
|
||||
**Required actions:** The generator option `no_unions` can be used to
|
||||
restore old behaviour and to allow callbacks to be used. To use unions,
|
||||
one change is needed: use `which_xxxx` field to detect which field is
|
||||
present, instead of `has_xxxx`. Compare the value against
|
||||
`MyStruct_myfield_tag`.
|
||||
|
||||
**Error indications:** Generator error: `"Callback fields inside of
|
||||
oneof are not supported"`. Compiler error: `"Message"` has no member
|
||||
named `"has_xxxx"`.
|
||||
|
||||
Nanopb-0.3.0 (2014-08-26)
|
||||
-------------------------
|
||||
|
||||
### Separate field iterator logic to pb_common.c
|
||||
|
||||
**Rationale:** Originally, the field iteration logic was simple enough
|
||||
to be duplicated in `pb_decode.c` and `pb_encode.c`. New field types
|
||||
have made the logic more complex, which required the creation of a new
|
||||
file to contain the common functionality.
|
||||
|
||||
**Changes:** There is a new file, `pb_common.c`, which must be included
|
||||
in builds.
|
||||
|
||||
**Required actions:** Add `pb_common.c` to build rules. This file is
|
||||
always required. Either `pb_decode.c` or `pb_encode.c` can still be
|
||||
left out if some functionality is not needed.
|
||||
|
||||
**Error indications:** Linker error: undefined reference to
|
||||
`pb_field_iter_begin`, `pb_field_iter_next` or similar.
|
||||
|
||||
### Change data type of field counts to pb_size_t
|
||||
|
||||
**Rationale:** Often nanopb is used with small arrays, such as 255 items
|
||||
or less. Using a full `size_t` field to store the array count wastes
|
||||
memory if there are many arrays. There already exists parameters
|
||||
`PB_FIELD_16BIT` and `PB_FIELD_32BIT` which tell nanopb what is the
|
||||
maximum size of arrays in use.
|
||||
|
||||
**Changes:** Generator will now use `pb_size_t` for the array
|
||||
`_count` fields. The size of the type will be controlled by the
|
||||
`PB_FIELD_16BIT` and `PB_FIELD_32BIT` compilation time options.
|
||||
|
||||
**Required actions:** Regenerate all `.pb.h` files. In some cases casts
|
||||
to the `pb_size_t` type may need to be added in the user code when
|
||||
accessing the `_count` fields.
|
||||
|
||||
**Error indications:** Incorrect data at runtime, crashes. But note that
|
||||
other changes in the same version already require regenerating the files
|
||||
and have better indications of errors, so this is only an issue for
|
||||
development versions.
|
||||
|
||||
### Renamed some macros and identifiers
|
||||
|
||||
**Rationale:** Some names in nanopb core were badly chosen and
|
||||
conflicted with ISO C99 reserved names or lacked a prefix. While they
|
||||
haven\'t caused trouble so far, it is reasonable to switch to
|
||||
non-conflicting names as these are rarely used from user code.
|
||||
|
||||
**Changes:** The following identifier names have changed:
|
||||
|
||||
- Macros:
|
||||
- STATIC_ASSERT(x) -> PB_STATIC_ASSERT(x)
|
||||
- UNUSED(x) -> PB_UNUSED(x)
|
||||
- Include guards:
|
||||
- PB_filename -> PB_filename_INCLUDED
|
||||
- Structure forward declaration tags:
|
||||
- _pb_field_t -> pb_field_s
|
||||
- _pb_bytes_array_t -> pb_bytes_array_s
|
||||
- _pb_callback_t -> pb_callback_s
|
||||
- _pb_extension_type_t -> pb_extension_type_s
|
||||
- _pb_extension_t -> pb_extension_s
|
||||
- _pb_istream_t -> pb_istream_s
|
||||
- _pb_ostream_t -> pb_ostream_s
|
||||
|
||||
**Required actions:** Regenerate all `.pb.c` files. If you use any of
|
||||
the above identifiers in your application code, perform search-replace
|
||||
to the new name.
|
||||
|
||||
**Error indications:** Compiler errors on lines with the macro/type
|
||||
names.
|
||||
|
||||
Nanopb-0.2.9 (2014-08-09)
|
||||
-------------------------
|
||||
|
||||
### Change semantics of generator -e option
|
||||
|
||||
**Rationale:** Some compilers do not accept filenames with two dots
|
||||
(like in default extension .pb.c). The `-e` option to the generator
|
||||
allowed changing the extension, but not skipping the extra dot.
|
||||
|
||||
**Changes:** The `-e` option in generator will no longer add the
|
||||
prepending dot. The default value has been adjusted accordingly to
|
||||
`.pb.c` to keep the default behaviour the same as before.
|
||||
|
||||
**Required actions:** Only if using the generator -e option. Add dot
|
||||
before the parameter value on the command line.
|
||||
|
||||
**Error indications:** File not found when trying to compile generated
|
||||
files.
|
||||
|
||||
Nanopb-0.2.7 (2014-04-07)
|
||||
-------------------------
|
||||
|
||||
### Changed pointer-type bytes field datatype
|
||||
|
||||
**Rationale:** In the initial pointer encoding support since
|
||||
nanopb-0.2.5, the bytes type used a separate `pb_bytes_ptr_t` type to
|
||||
represent `bytes` fields. This made it easy to encode data from a
|
||||
separate, user-allocated buffer. However, it made the internal logic
|
||||
more complex and was inconsistent with the other types.
|
||||
|
||||
**Changes:** Dynamically allocated bytes fields now have the
|
||||
`pb_bytes_array_t` type, just like statically allocated ones.
|
||||
|
||||
**Required actions:** Only if using pointer-type fields with the bytes
|
||||
datatype. Change any access to `msg->field.size` to
|
||||
`msg->field->size`. Change any allocation to reserve space of amount
|
||||
`PB_BYTES_ARRAY_T_ALLOCSIZE(n)`. If the data pointer was begin
|
||||
assigned from external source, implement the field using a callback
|
||||
function instead.
|
||||
|
||||
**Error indications:** Compiler error: unknown type name
|
||||
`pb_bytes_ptr_t`.
|
||||
|
||||
Nanopb-0.2.4 (2013-11-07)
|
||||
-------------------------
|
||||
|
||||
### Remove the NANOPB_INTERNALS compilation option
|
||||
|
||||
**Rationale:** Having the option in the headers required the functions
|
||||
to be non-static, even if the option is not used. This caused errors on
|
||||
some static analysis tools.
|
||||
|
||||
**Changes:** The `\#ifdef` and associated functions were removed from
|
||||
the header.
|
||||
|
||||
**Required actions:** Only if the `NANOPB_INTERNALS` option was
|
||||
previously used. Actions are as listed under nanopb-0.1.3 and
|
||||
nanopb-0.1.6.
|
||||
|
||||
**Error indications:** Compiler warning: implicit declaration of
|
||||
function `pb_dec_string`, `pb_enc_string`, or similar.
|
||||
|
||||
Nanopb-0.2.1 (2013-04-14)
|
||||
-------------------------
|
||||
|
||||
### Callback function signature
|
||||
|
||||
**Rationale:** Previously the auxiliary data to field callbacks was
|
||||
passed as `void*`. This allowed passing of any data, but made it
|
||||
unnecessarily complex to return a pointer from callback.
|
||||
|
||||
**Changes:** The callback function parameter was changed to `void**`.
|
||||
|
||||
**Required actions:** You can continue using the old callback style by
|
||||
defining `PB_OLD_CALLBACK_STYLE`. Recommended action is to:
|
||||
|
||||
- Change the callback signatures to contain `void**` for decoders and `void * const *` for encoders.
|
||||
- Change the callback function body to use **arg` instead of `arg`.
|
||||
|
||||
**Error indications:** Compiler warning: assignment from incompatible
|
||||
pointer type, when initializing `funcs.encode` or `funcs.decode`.
|
||||
|
||||
Nanopb-0.2.0 (2013-03-02)
|
||||
-------------------------
|
||||
|
||||
### Reformatted generated .pb.c file using macros
|
||||
|
||||
**Rationale:** Previously the generator made a list of C `pb_field_t`
|
||||
initializers in the .pb.c file. This led to a need to regenerate all
|
||||
.pb.c files after even small changes to the `pb_field_t` definition.
|
||||
|
||||
**Changes:** Macros were added to pb.h which allow for cleaner
|
||||
definition of the .pb.c contents. By changing the macro definitions,
|
||||
changes to the field structure are possible without breaking
|
||||
compatibility with old .pb.c files.
|
||||
|
||||
**Required actions:** Regenerate all .pb.c files from the .proto
|
||||
sources.
|
||||
|
||||
**Error indications:** Compiler warning: implicit declaration of
|
||||
function `pb_delta_end`.
|
||||
|
||||
### Changed pb_type_t definitions
|
||||
|
||||
**Rationale:** The `pb_type_t` was previously an enumeration type.
|
||||
This caused warnings on some compilers when using bitwise operations to
|
||||
set flags inside the values.
|
||||
|
||||
**Changes:** The `pb_type_t` was changed to *typedef uint8_t*. The
|
||||
values were changed to `#define`. Some value names were changed for
|
||||
consistency.
|
||||
|
||||
**Required actions:** Only if you directly access the
|
||||
`pb_field_t` contents in your own code, something which is
|
||||
not usually done. Needed changes:
|
||||
|
||||
- Change `PB_HTYPE_ARRAY` to `PB_HTYPE_REPEATED`.
|
||||
- Change `PB_HTYPE_CALLBACK` to `PB_ATYPE()` and `PB_ATYPE_CALLBACK`.
|
||||
|
||||
**Error indications:** Compiler error: `PB_HTYPE_ARRAY` or
|
||||
`PB_HTYPE_CALLBACK` undeclared.
|
||||
|
||||
Nanopb-0.1.6 (2012-09-02)
|
||||
-------------------------
|
||||
|
||||
### Refactored field decoder interface
|
||||
|
||||
**Rationale:** Similarly to field encoders in nanopb-0.1.3.
|
||||
|
||||
**Changes:** New functions with names `pb_decode_*` were added.
|
||||
|
||||
**Required actions:** By defining NANOPB_INTERNALS, you can still keep
|
||||
using the old functions. Recommended action is to replace any calls with
|
||||
the newer `pb_decode_*` equivalents.
|
||||
|
||||
**Error indications:** Compiler warning: implicit declaration of
|
||||
function `pb_dec_string`, `pb_dec_varint`, `pb_dec_submessage` or
|
||||
similar.
|
||||
|
||||
Nanopb-0.1.3 (2012-06-12)
|
||||
-------------------------
|
||||
|
||||
### Refactored field encoder interface
|
||||
|
||||
**Rationale:** The old `pb_enc_*` functions were designed mostly for
|
||||
the internal use by the core. Because they are internally accessed
|
||||
through function pointers, their signatures had to be common. This led
|
||||
to a confusing interface for external users.
|
||||
|
||||
**Changes:** New functions with names `pb_encode_*` were added. These
|
||||
have easier to use interfaces. The old functions are now only thin
|
||||
wrappers for the new interface.
|
||||
|
||||
**Required actions:** By defining NANOPB_INTERNALS, you can still keep
|
||||
using the old functions. Recommended action is to replace any calls with
|
||||
the newer `pb_encode_*` equivalents.
|
||||
|
||||
**Error indications:** Compiler warning: implicit declaration of
|
||||
function `pb_enc_string`, *pb_enc_varint,`pb_enc_submessage\` or
|
||||
similar.
|
1036
third_party/nanopb/docs/reference.md
vendored
Normal file
1036
third_party/nanopb/docs/reference.md
vendored
Normal file
File diff suppressed because it is too large
Load diff
92
third_party/nanopb/docs/security.md
vendored
Normal file
92
third_party/nanopb/docs/security.md
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
# Nanopb: Security model
|
||||
|
||||
Importance of security in a Protocol Buffers library
|
||||
----------------------------------------------------
|
||||
|
||||
In the context of protocol buffers, security comes into play when
|
||||
decoding untrusted data. Naturally, if the attacker can modify the
|
||||
contents of a protocol buffers message, he can feed the application any
|
||||
values possible. Therefore the application itself must be prepared to
|
||||
receive untrusted values.
|
||||
|
||||
Where nanopb plays a part is preventing the attacker from running
|
||||
arbitrary code on the target system. Mostly this means that there must
|
||||
not be any possibility to cause buffer overruns, memory corruption or
|
||||
invalid pointers by the means of crafting a malicious message.
|
||||
|
||||
Division of trusted and untrusted data
|
||||
--------------------------------------
|
||||
|
||||
The following data is regarded as **trusted**. It must be under the
|
||||
control of the application writer. Malicious data in these structures
|
||||
could cause security issues, such as execution of arbitrary code:
|
||||
|
||||
1. Callback, pointer and extension fields in message structures given
|
||||
to pb_encode() and pb_decode(). These fields are memory pointers,
|
||||
and are generated depending on the message definition in the .proto
|
||||
file.
|
||||
2. The automatically generated field definitions, i.e.
|
||||
`pb_msgdesc_t`.
|
||||
3. Contents of the `pb_istream_t` and `pb_ostream_t` structures
|
||||
(this does not mean the contents of the stream itself, just the
|
||||
stream definition).
|
||||
|
||||
The following data is regarded as **untrusted**. Invalid/malicious data
|
||||
in these will cause "garbage in, garbage out" behaviour. It will not
|
||||
cause buffer overflows, information disclosure or other security
|
||||
problems:
|
||||
|
||||
1. All data read from `pb_istream_t`.
|
||||
2. All fields in message structures, except:
|
||||
- callbacks (`pb_callback_t` structures)
|
||||
- pointer fields and `_count` fields for pointers
|
||||
- extensions (`pb_extension_t` structures)
|
||||
|
||||
Invariants
|
||||
----------
|
||||
|
||||
The following invariants are maintained during operation, even if the
|
||||
untrusted data has been maliciously crafted:
|
||||
|
||||
1. Nanopb will never read more than `bytes_left` bytes from
|
||||
`pb_istream_t`.
|
||||
2. Nanopb will never write more than `max_size` bytes to
|
||||
`pb_ostream_t`.
|
||||
3. Nanopb will never access memory out of bounds of the message
|
||||
structure.
|
||||
4. After `pb_decode()` returns successfully, the message structure will
|
||||
be internally consistent:
|
||||
- The `count` fields of arrays will not exceed the array size.
|
||||
- The `size` field of bytes will not exceed the allocated size.
|
||||
- All string fields will have null terminator.
|
||||
- bool fields will have valid true/false values (since
|
||||
nanopb-0.3.9.4)
|
||||
- pointer fields will be either `NULL` or point to valid data
|
||||
5. After `pb_encode()` returns successfully, the resulting message is a
|
||||
valid protocol buffers message. (Except if user-defined callbacks
|
||||
write incorrect data.)
|
||||
6. All memory allocated by `pb_decode()` will be released by a subsequent
|
||||
call to `pb_release()` on the same message.
|
||||
|
||||
Further considerations
|
||||
----------------------
|
||||
|
||||
Even if the nanopb library is free of any security issues, there are
|
||||
still several possible attack vectors that the application author must
|
||||
consider. The following list is not comprehensive:
|
||||
|
||||
1. Stack usage may depend on the contents of the message. The message
|
||||
definition places an upper bound on how much stack will be used.
|
||||
Tests should be run with all fields present, to record the maximum
|
||||
possible stack usage.
|
||||
2. Callbacks can do anything. The code for the callbacks must be
|
||||
carefully checked if they are used with untrusted data.
|
||||
3. If using stream input, a maximum size should be set in
|
||||
`pb_istream_t` to stop a denial of service attack from using an
|
||||
infinite message.
|
||||
4. If using network sockets as streams, a timeout should be set to stop
|
||||
denial of service attacks.
|
||||
5. If using `malloc()` support, some method of limiting memory use
|
||||
should be employed. This can be done by defining custom
|
||||
`pb_realloc()` function. Nanopb will properly detect and handle
|
||||
failed memory allocations.
|
173
third_party/nanopb/docs/whats_new.md
vendored
Normal file
173
third_party/nanopb/docs/whats_new.md
vendored
Normal file
|
@ -0,0 +1,173 @@
|
|||
# Nanopb: New features in nanopb 0.4
|
||||
|
||||
## What's new in nanopb 0.4
|
||||
|
||||
Long in the making, nanopb 0.4 has seen some wide reaching improvements
|
||||
in reaction to the development of the rest of the protobuf ecosystem.
|
||||
This document showcases features that are not immediately visible, but
|
||||
that you may want to take advantage of.
|
||||
|
||||
A lot of effort has been spent in retaining backwards and forwards
|
||||
compatibility with previous nanopb versions. For a list of breaking
|
||||
changes, see [migration document](migration.html)
|
||||
|
||||
### New field descriptor format
|
||||
|
||||
The basic design of nanopb has always been that the information about
|
||||
messages is stored in a compact descriptor format, which is iterated in
|
||||
runtime. Initially it was very tightly tied with encoder and decoder
|
||||
logic.
|
||||
|
||||
In nanopb-0.3.0 the field iteration logic was separated to
|
||||
`pb_common.c`. Already at that point it was clear that the old format
|
||||
was getting too limited, but it wasn't extended at that time.
|
||||
|
||||
Now in 0.4, the descriptor format was completely decoupled from the
|
||||
encoder and decoder logic, and redesigned to meet new demands.
|
||||
Previously each field was stored as `pb_field_t` struct, which was
|
||||
between 8 and 32 bytes in size, depending on compilation options and
|
||||
platform. Now information about fields is stored as a variable length
|
||||
sequence of `uint32_t` data words. There are 1, 2, 4 and 8 word formats,
|
||||
with the 8 word format containing plenty of space for future
|
||||
extensibility.
|
||||
|
||||
One benefit of the variable length format is that most messages now take
|
||||
less storage space. Most fields use 2 words, while simple fields in
|
||||
small messages require only 1 word. Benefit is larger if code previously
|
||||
required `PB_FIELD_16BIT` or `PB_FIELD_32BIT` options. In
|
||||
the `AllTypes` test case, 0.3 had data size of 1008 bytes in
|
||||
8-bit configuration and 1408 bytes in 16-bit configuration. New format
|
||||
in 0.4 takes 896 bytes for either of these.
|
||||
|
||||
In addition, the new decoupling has allowed moving most of the field
|
||||
descriptor data into FLASH on Harvard architectures, such as AVR.
|
||||
Previously nanopb was quite RAM-heavy on AVR, which cannot put normal
|
||||
constants in flash like most other platforms do.
|
||||
|
||||
### Python packaging for generator
|
||||
|
||||
Nanopb generator is now available as a Python package, installable using
|
||||
`pip` package manager. This will reduce the need for binary
|
||||
packages, as if you have Python already installed you can just
|
||||
`pip install nanopb` and have the generator available on path as
|
||||
`nanopb_generator`.
|
||||
|
||||
The generator can also take advantage of the Python-based `protoc`
|
||||
available in `grpcio-tools` Python package. If you also install that,
|
||||
there is no longer a need to have binary `protoc` available.
|
||||
|
||||
### Generator now automatically calls protoc
|
||||
|
||||
Initially, nanopb generator was used in two steps: first calling
|
||||
`protoc` to parse the `.proto` file into `.pb` binary
|
||||
format, and then calling `nanopb_generator.py` to output the
|
||||
`.pb.h` and `.pb.c` files.
|
||||
|
||||
Nanopb 0.2.3 added support for running as a `protoc` plugin, which
|
||||
allowed single-step generation using `--nanopb_out` parameter. However,
|
||||
the plugin mode has two complications: passing options to nanopb
|
||||
generator itself becomes more difficult, and the generator does not know
|
||||
the actual path of input files. The second limitation has been
|
||||
particularly problematic for locating `.options` files.
|
||||
|
||||
Both of these older methods still work and will remain supported.
|
||||
However, now `nanopb_generator` can also take `.proto` files
|
||||
directly and it will transparently call `protoc` in the background.
|
||||
|
||||
### Callbacks bound by function name
|
||||
|
||||
Since its very beginnings, nanopb has supported field callbacks to allow
|
||||
processing structures that are larger than what could fit in memory at
|
||||
once. So far the callback functions have been stored in the message
|
||||
structure in a `pb_callback_t` struct.
|
||||
|
||||
Storing pointers along with user data is somewhat risky from a security
|
||||
point of view. In addition it has caused problems with `oneof` fields,
|
||||
which reuse the same storage space for multiple submessages. Because
|
||||
there is no separate area for each submessage, there is no space to
|
||||
store the callback pointers either.
|
||||
|
||||
Nanopb-0.4.0 introduces callbacks that are referenced by the function
|
||||
name instead of setting the pointers separately. This should work well
|
||||
for most applications that have a single callback function for each
|
||||
message type. For more complex needs, `pb_callback_t` will also remain
|
||||
supported.
|
||||
|
||||
Function name callbacks also allow specifying custom data types for
|
||||
inclusion in the message structure. For example, you could have
|
||||
`MyObject*` pointer along with other message fields, and then process
|
||||
that object in custom way in your callback.
|
||||
|
||||
This feature is demonstrated in
|
||||
[tests/oneof_callback](https://github.com/nanopb/nanopb/tree/master/tests/oneof_callback) test case and
|
||||
[examples/network_server](https://github.com/nanopb/nanopb/tree/master/examples/network_server) example.
|
||||
|
||||
### Message level callback for oneofs
|
||||
|
||||
As mentioned above, callbacks inside submessages inside oneofs have been
|
||||
problematic to use. To make using `pb_callback_t`-style callbacks there
|
||||
possible, a new generator option `submsg_callback` was added.
|
||||
|
||||
Setting this option to true will cause a new message level callback to
|
||||
be added before the `which_field` of the oneof. This callback will be
|
||||
called when the submessage tag number is known, but before the actual
|
||||
message is decoded. The callback can either choose to set callback
|
||||
pointers inside the submessage, or just completely decode the submessage
|
||||
there and then. If any unread data remains after the callback returns,
|
||||
normal submessage decoding will continue.
|
||||
|
||||
There is an example of this in [tests/oneof_callback](https://github.com/nanopb/nanopb/tree/master/tests/oneof_callback) test case.
|
||||
|
||||
### Binding message types to custom structures
|
||||
|
||||
It is often said that good C code is chock full of macros. Or maybe I
|
||||
got it wrong. But since nanopb 0.2, the field descriptor generation has
|
||||
heavily relied on macros. This allows it to automatically adapt to
|
||||
differences in type alignment on different platforms, and to decouple
|
||||
the Python generation logic from how the message descriptors are
|
||||
implemented on the C side.
|
||||
|
||||
Now in 0.4.0, I've made the macros even more abstract. Time will tell
|
||||
whether this was such a great idea that I think it is, but now the
|
||||
complete list of fields in each message is available in `.pb.h` file.
|
||||
This allows a kind of metaprogramming using [X-macros]()
|
||||
|
||||
One feature that this can be used for is binding the message descriptor
|
||||
to a custom structure or C++ class type. You could have a bunch of other
|
||||
fields in the structure and even the datatypes can be different to an
|
||||
extent, and nanopb will automatically detect the size and position of
|
||||
each field. The generated `.pb.c` files now just have calls of
|
||||
`PB_BIND(msgname, structname, width)`. Adding a similar
|
||||
call to your own code will bind the message to your own structure.
|
||||
|
||||
### UTF-8 validation
|
||||
|
||||
Protobuf format defines that strings should consist of valid UTF-8
|
||||
codepoints. Previously nanopb has not enforced this, requiring extra
|
||||
care in the user code. Now optional UTF-8 validation is available with
|
||||
compilation option `PB_VALIDATE_UTF8`.
|
||||
|
||||
### Double to float conversion
|
||||
|
||||
Some platforms such as `AVR` do not support the `double`
|
||||
datatype, instead making it an alias for `float`. This has resulted in
|
||||
problems when trying to process message types containing `double` fields
|
||||
generated on other machines. There has been an example on how to
|
||||
manually perform the conversion between `double` and
|
||||
`float`.
|
||||
|
||||
Now that example is integrated as an optional feature in nanopb core. By
|
||||
defining `PB_CONVERT_DOUBLE_FLOAT`, the required conversion between 32-
|
||||
and 64-bit floating point formats happens automatically on decoding and
|
||||
encoding.
|
||||
|
||||
### Improved testing
|
||||
|
||||
Testing on embedded platforms has been integrated in the continuous
|
||||
testing environment. Now all of the 80+ test cases are automatically run
|
||||
on STM32 and AVR targets. Previously only a few specialized test cases
|
||||
were manually tested on embedded systems.
|
||||
|
||||
Nanopb fuzzer has also been integrated in Google's [OSSFuzz](https://google.github.io/oss-fuzz/)
|
||||
platform, giving a huge boost in the CPU power available for randomized
|
||||
testing.
|
18
third_party/nanopb/examples/cmake_relpath/README.txt
vendored
Normal file
18
third_party/nanopb/examples/cmake_relpath/README.txt
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
Nanopb example "simple" using CMake
|
||||
=======================
|
||||
|
||||
This example is the same as the simple nanopb example but built using CMake.
|
||||
|
||||
Example usage
|
||||
-------------
|
||||
|
||||
On Linux, create a build directory and then call cmake:
|
||||
|
||||
nanopb/examples/cmake_simple$ mkdir build
|
||||
nanopb/examples/cmake_simple$ cd build/
|
||||
nanopb/examples/cmake_simple/build$ cmake ..
|
||||
nanopb/examples/cmake_simple/build$ make
|
||||
|
||||
After that, you can run it with the command: ./simple
|
||||
|
||||
On other platforms supported by CMake, refer to CMake instructions.
|
11
third_party/nanopb/examples/cmake_relpath/proto/simple.proto
vendored
Normal file
11
third_party/nanopb/examples/cmake_relpath/proto/simple.proto
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
// A very simple protocol definition, consisting of only
|
||||
// one message.
|
||||
syntax = "proto2";
|
||||
|
||||
import "sub/unlucky.proto";
|
||||
|
||||
message SimpleMessage {
|
||||
required int32 lucky_number = 1;
|
||||
required UnluckyNumber unlucky = 2;
|
||||
}
|
||||
|
5
third_party/nanopb/examples/cmake_relpath/proto/sub/unlucky.proto
vendored
Normal file
5
third_party/nanopb/examples/cmake_relpath/proto/sub/unlucky.proto
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
syntax = "proto2";
|
||||
|
||||
message UnluckyNumber {
|
||||
required uint32 number = 1;
|
||||
}
|
73
third_party/nanopb/examples/cmake_relpath/simple.c
vendored
Normal file
73
third_party/nanopb/examples/cmake_relpath/simple.c
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
#include <stdio.h>
|
||||
#include <pb_encode.h>
|
||||
#include <pb_decode.h>
|
||||
#include "simple.pb.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
/* This is the buffer where we will store our message. */
|
||||
uint8_t buffer[128];
|
||||
size_t message_length;
|
||||
bool status;
|
||||
|
||||
/* Encode our message */
|
||||
{
|
||||
/* Allocate space on the stack to store the message data.
|
||||
*
|
||||
* Nanopb generates simple struct definitions for all the messages.
|
||||
* - check out the contents of simple.pb.h!
|
||||
* It is a good idea to always initialize your structures
|
||||
* so that you do not have garbage data from RAM in there.
|
||||
*/
|
||||
SimpleMessage message = SimpleMessage_init_zero;
|
||||
|
||||
/* Create a stream that will write to our buffer. */
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
|
||||
/* Fill in the lucky number */
|
||||
message.lucky_number = 13;
|
||||
message.unlucky.number = 42;
|
||||
|
||||
/* Now we are ready to encode the message! */
|
||||
status = pb_encode(&stream, SimpleMessage_fields, &message);
|
||||
message_length = stream.bytes_written;
|
||||
|
||||
/* Then just check for any errors.. */
|
||||
if (!status)
|
||||
{
|
||||
printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we could transmit the message over network, store it in a file or
|
||||
* wrap it to a pigeon's leg.
|
||||
*/
|
||||
|
||||
/* But because we are lazy, we will just decode it immediately. */
|
||||
|
||||
{
|
||||
/* Allocate space for the decoded message. */
|
||||
SimpleMessage message = SimpleMessage_init_zero;
|
||||
|
||||
/* Create a stream that reads from the buffer. */
|
||||
pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
|
||||
|
||||
/* Now we are ready to decode the message. */
|
||||
status = pb_decode(&stream, SimpleMessage_fields, &message);
|
||||
|
||||
/* Check for errors... */
|
||||
if (!status)
|
||||
{
|
||||
printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Print the data contained in the message. */
|
||||
printf("Your lucky number was %d!\n", message.lucky_number);
|
||||
printf("Your unlucky number was %u!\n", message.unlucky.number);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
18
third_party/nanopb/examples/cmake_simple/README.txt
vendored
Normal file
18
third_party/nanopb/examples/cmake_simple/README.txt
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
Nanopb example "simple" using CMake
|
||||
=======================
|
||||
|
||||
This example is the same as the simple nanopb example but built using CMake.
|
||||
|
||||
Example usage
|
||||
-------------
|
||||
|
||||
On Linux, create a build directory and then call cmake:
|
||||
|
||||
nanopb/examples/cmake_simple$ mkdir build
|
||||
nanopb/examples/cmake_simple$ cd build/
|
||||
nanopb/examples/cmake_simple/build$ cmake ..
|
||||
nanopb/examples/cmake_simple/build$ make
|
||||
|
||||
After that, you can run it with the command: ./simple
|
||||
|
||||
On other platforms supported by CMake, refer to CMake instructions.
|
71
third_party/nanopb/examples/cmake_simple/simple.c
vendored
Normal file
71
third_party/nanopb/examples/cmake_simple/simple.c
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
#include <stdio.h>
|
||||
#include <pb_encode.h>
|
||||
#include <pb_decode.h>
|
||||
#include "simple.pb.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
/* This is the buffer where we will store our message. */
|
||||
uint8_t buffer[128];
|
||||
size_t message_length;
|
||||
bool status;
|
||||
|
||||
/* Encode our message */
|
||||
{
|
||||
/* Allocate space on the stack to store the message data.
|
||||
*
|
||||
* Nanopb generates simple struct definitions for all the messages.
|
||||
* - check out the contents of simple.pb.h!
|
||||
* It is a good idea to always initialize your structures
|
||||
* so that you do not have garbage data from RAM in there.
|
||||
*/
|
||||
SimpleMessage message = SimpleMessage_init_zero;
|
||||
|
||||
/* Create a stream that will write to our buffer. */
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
|
||||
/* Fill in the lucky number */
|
||||
message.lucky_number = 13;
|
||||
|
||||
/* Now we are ready to encode the message! */
|
||||
status = pb_encode(&stream, SimpleMessage_fields, &message);
|
||||
message_length = stream.bytes_written;
|
||||
|
||||
/* Then just check for any errors.. */
|
||||
if (!status)
|
||||
{
|
||||
printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we could transmit the message over network, store it in a file or
|
||||
* wrap it to a pigeon's leg.
|
||||
*/
|
||||
|
||||
/* But because we are lazy, we will just decode it immediately. */
|
||||
|
||||
{
|
||||
/* Allocate space for the decoded message. */
|
||||
SimpleMessage message = SimpleMessage_init_zero;
|
||||
|
||||
/* Create a stream that reads from the buffer. */
|
||||
pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
|
||||
|
||||
/* Now we are ready to decode the message. */
|
||||
status = pb_decode(&stream, SimpleMessage_fields, &message);
|
||||
|
||||
/* Check for errors... */
|
||||
if (!status)
|
||||
{
|
||||
printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Print the data contained in the message. */
|
||||
printf("Your lucky number was %d!\n", message.lucky_number);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
9
third_party/nanopb/examples/cmake_simple/simple.proto
vendored
Normal file
9
third_party/nanopb/examples/cmake_simple/simple.proto
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
// A very simple protocol definition, consisting of only
|
||||
// one message.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
message SimpleMessage {
|
||||
required int32 lucky_number = 1;
|
||||
}
|
||||
|
17
third_party/nanopb/examples/network_server/Makefile
vendored
Normal file
17
third_party/nanopb/examples/network_server/Makefile
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Include the nanopb provided Makefile rules
|
||||
include ../../extra/nanopb.mk
|
||||
|
||||
# Compiler flags to enable all warnings & debug info
|
||||
CFLAGS = -ansi -Wall -Werror -g -O0
|
||||
CFLAGS += -I$(NANOPB_DIR)
|
||||
|
||||
all: server client
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
clean:
|
||||
rm -f server client fileproto.pb.c fileproto.pb.h
|
||||
|
||||
%: %.c common.c fileproto.pb.c
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(NANOPB_CORE)
|
||||
|
60
third_party/nanopb/examples/network_server/README.txt
vendored
Normal file
60
third_party/nanopb/examples/network_server/README.txt
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
Nanopb example "network_server"
|
||||
===============================
|
||||
|
||||
This example demonstrates the use of nanopb to communicate over network
|
||||
connections. It consists of a server that sends file listings, and of
|
||||
a client that requests the file list from the server.
|
||||
|
||||
Example usage
|
||||
-------------
|
||||
|
||||
user@host:~/nanopb/examples/network_server$ make # Build the example
|
||||
protoc -ofileproto.pb fileproto.proto
|
||||
python ../../generator/nanopb_generator.py fileproto.pb
|
||||
Writing to fileproto.pb.h and fileproto.pb.c
|
||||
cc -ansi -Wall -Werror -I .. -g -O0 -I../.. -o server server.c
|
||||
../../pb_decode.c ../../pb_encode.c fileproto.pb.c common.c
|
||||
cc -ansi -Wall -Werror -I .. -g -O0 -I../.. -o client client.c
|
||||
../../pb_decode.c ../../pb_encode.c fileproto.pb.c common.c
|
||||
|
||||
user@host:~/nanopb/examples/network_server$ ./server & # Start the server on background
|
||||
[1] 24462
|
||||
|
||||
petteri@oddish:~/nanopb/examples/network_server$ ./client /bin # Request the server to list /bin
|
||||
Got connection.
|
||||
Listing directory: /bin
|
||||
1327119 bzdiff
|
||||
1327126 bzless
|
||||
1327147 ps
|
||||
1327178 ntfsmove
|
||||
1327271 mv
|
||||
1327187 mount
|
||||
1327259 false
|
||||
1327266 tempfile
|
||||
1327285 zfgrep
|
||||
1327165 gzexe
|
||||
1327204 nc.openbsd
|
||||
1327260 uname
|
||||
|
||||
|
||||
Details of implementation
|
||||
-------------------------
|
||||
fileproto.proto contains the portable Google Protocol Buffers protocol definition.
|
||||
It could be used as-is to implement a server or a client in any other language, for
|
||||
example Python or Java.
|
||||
|
||||
fileproto.options contains the nanopb-specific options for the protocol file. This
|
||||
sets the amount of space allocated for file names when decoding messages.
|
||||
|
||||
common.c/h contains functions that allow nanopb to read and write directly from
|
||||
network socket. This way there is no need to allocate a separate buffer to store
|
||||
the message.
|
||||
|
||||
server.c contains the code to open a listening socket, to respond to clients and
|
||||
to list directory contents.
|
||||
|
||||
client.c contains the code to connect to a server, to send a request and to print
|
||||
the response message.
|
||||
|
||||
The code is implemented using the POSIX socket api, but it should be easy enough
|
||||
to port into any other socket api, such as lwip.
|
138
third_party/nanopb/examples/network_server/client.c
vendored
Normal file
138
third_party/nanopb/examples/network_server/client.c
vendored
Normal file
|
@ -0,0 +1,138 @@
|
|||
/* This is a simple TCP client that connects to port 1234 and prints a list
|
||||
* of files in a given directory.
|
||||
*
|
||||
* It directly deserializes and serializes messages from network, minimizing
|
||||
* memory use.
|
||||
*
|
||||
* For flexibility, this example is implemented using posix api.
|
||||
* In a real embedded system you would typically use some other kind of
|
||||
* a communication and filesystem layer.
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pb_encode.h>
|
||||
#include <pb_decode.h>
|
||||
|
||||
#include "fileproto.pb.h"
|
||||
#include "common.h"
|
||||
|
||||
/* This callback function will be called once for each filename received
|
||||
* from the server. The filenames will be printed out immediately, so that
|
||||
* no memory has to be allocated for them.
|
||||
*/
|
||||
bool ListFilesResponse_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field)
|
||||
{
|
||||
PB_UNUSED(ostream);
|
||||
if (istream != NULL && field->tag == ListFilesResponse_file_tag)
|
||||
{
|
||||
FileInfo fileinfo = {};
|
||||
|
||||
if (!pb_decode(istream, FileInfo_fields, &fileinfo))
|
||||
return false;
|
||||
|
||||
printf("%-10lld %s\n", (long long)fileinfo.inode, fileinfo.name);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* This function sends a request to socket 'fd' to list the files in
|
||||
* directory given in 'path'. The results received from server will
|
||||
* be printed to stdout.
|
||||
*/
|
||||
bool listdir(int fd, char *path)
|
||||
{
|
||||
/* Construct and send the request to server */
|
||||
{
|
||||
ListFilesRequest request = {};
|
||||
pb_ostream_t output = pb_ostream_from_socket(fd);
|
||||
|
||||
/* In our protocol, path is optional. If it is not given,
|
||||
* the server will list the root directory. */
|
||||
if (path == NULL)
|
||||
{
|
||||
request.has_path = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
request.has_path = true;
|
||||
if (strlen(path) + 1 > sizeof(request.path))
|
||||
{
|
||||
fprintf(stderr, "Too long path.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
strcpy(request.path, path);
|
||||
}
|
||||
|
||||
/* Encode the request. It is written to the socket immediately
|
||||
* through our custom stream. */
|
||||
if (!pb_encode_delimited(&output, ListFilesRequest_fields, &request))
|
||||
{
|
||||
fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&output));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read back the response from server */
|
||||
{
|
||||
ListFilesResponse response = {};
|
||||
pb_istream_t input = pb_istream_from_socket(fd);
|
||||
|
||||
if (!pb_decode_delimited(&input, ListFilesResponse_fields, &response))
|
||||
{
|
||||
fprintf(stderr, "Decode failed: %s\n", PB_GET_ERROR(&input));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the message from server decodes properly, but directory was
|
||||
* not found on server side, we get path_error == true. */
|
||||
if (response.path_error)
|
||||
{
|
||||
fprintf(stderr, "Server reported error.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int sockfd;
|
||||
struct sockaddr_in servaddr;
|
||||
char *path = NULL;
|
||||
|
||||
if (argc > 1)
|
||||
path = argv[1];
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
/* Connect to server running on localhost:1234 */
|
||||
memset(&servaddr, 0, sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
servaddr.sin_port = htons(1234);
|
||||
|
||||
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
|
||||
{
|
||||
perror("connect");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Send the directory listing request */
|
||||
if (!listdir(sockfd, path))
|
||||
return 2;
|
||||
|
||||
/* Close connection */
|
||||
close(sockfd);
|
||||
|
||||
return 0;
|
||||
}
|
43
third_party/nanopb/examples/network_server/common.c
vendored
Normal file
43
third_party/nanopb/examples/network_server/common.c
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* Simple binding of nanopb streams to TCP sockets.
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <pb_encode.h>
|
||||
#include <pb_decode.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static bool write_callback(pb_ostream_t *stream, const uint8_t *buf, size_t count)
|
||||
{
|
||||
int fd = (intptr_t)stream->state;
|
||||
return send(fd, buf, count, 0) == count;
|
||||
}
|
||||
|
||||
static bool read_callback(pb_istream_t *stream, uint8_t *buf, size_t count)
|
||||
{
|
||||
int fd = (intptr_t)stream->state;
|
||||
int result;
|
||||
|
||||
if (count == 0)
|
||||
return true;
|
||||
|
||||
result = recv(fd, buf, count, MSG_WAITALL);
|
||||
|
||||
if (result == 0)
|
||||
stream->bytes_left = 0; /* EOF */
|
||||
|
||||
return result == count;
|
||||
}
|
||||
|
||||
pb_ostream_t pb_ostream_from_socket(int fd)
|
||||
{
|
||||
pb_ostream_t stream = {&write_callback, (void*)(intptr_t)fd, SIZE_MAX, 0};
|
||||
return stream;
|
||||
}
|
||||
|
||||
pb_istream_t pb_istream_from_socket(int fd)
|
||||
{
|
||||
pb_istream_t stream = {&read_callback, (void*)(intptr_t)fd, SIZE_MAX};
|
||||
return stream;
|
||||
}
|
9
third_party/nanopb/examples/network_server/common.h
vendored
Normal file
9
third_party/nanopb/examples/network_server/common.h
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef _PB_EXAMPLE_COMMON_H_
|
||||
#define _PB_EXAMPLE_COMMON_H_
|
||||
|
||||
#include <pb.h>
|
||||
|
||||
pb_ostream_t pb_ostream_from_socket(int fd);
|
||||
pb_istream_t pb_istream_from_socket(int fd);
|
||||
|
||||
#endif
|
16
third_party/nanopb/examples/network_server/fileproto.options
vendored
Normal file
16
third_party/nanopb/examples/network_server/fileproto.options
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
# This file defines the nanopb-specific options for the messages defined
|
||||
# in fileproto.proto.
|
||||
#
|
||||
# If you come from high-level programming background, the hardcoded
|
||||
# maximum lengths may disgust you. However, if your microcontroller only
|
||||
# has a few kB of ram to begin with, setting reasonable limits for
|
||||
# filenames is ok.
|
||||
#
|
||||
# On the other hand, using the callback interface, it is not necessary
|
||||
# to set a limit on the number of files in the response.
|
||||
|
||||
* include:"sys/types.h"
|
||||
* include:"dirent.h"
|
||||
ListFilesResponse.file type:FT_CALLBACK, callback_datatype:"DIR*"
|
||||
ListFilesRequest.path max_size:128
|
||||
FileInfo.name max_size:128
|
20
third_party/nanopb/examples/network_server/fileproto.proto
vendored
Normal file
20
third_party/nanopb/examples/network_server/fileproto.proto
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
// This defines protocol for a simple server that lists files.
|
||||
//
|
||||
// See also the nanopb-specific options in fileproto.options.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
message ListFilesRequest {
|
||||
optional string path = 1 [default = "/"];
|
||||
}
|
||||
|
||||
message FileInfo {
|
||||
required uint64 inode = 1;
|
||||
required string name = 2;
|
||||
}
|
||||
|
||||
message ListFilesResponse {
|
||||
optional bool path_error = 1 [default = false];
|
||||
repeated FileInfo file = 2;
|
||||
}
|
||||
|
164
third_party/nanopb/examples/network_server/server.c
vendored
Normal file
164
third_party/nanopb/examples/network_server/server.c
vendored
Normal file
|
@ -0,0 +1,164 @@
|
|||
/* This is a simple TCP server that listens on port 1234 and provides lists
|
||||
* of files to clients, using a protocol defined in file_server.proto.
|
||||
*
|
||||
* It directly deserializes and serializes messages from network, minimizing
|
||||
* memory use.
|
||||
*
|
||||
* For flexibility, this example is implemented using posix api.
|
||||
* In a real embedded system you would typically use some other kind of
|
||||
* a communication and filesystem layer.
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pb_encode.h>
|
||||
#include <pb_decode.h>
|
||||
|
||||
#include "fileproto.pb.h"
|
||||
#include "common.h"
|
||||
|
||||
/* This callback function will be called during the encoding.
|
||||
* It will write out any number of FileInfo entries, without consuming unnecessary memory.
|
||||
* This is accomplished by fetching the filenames one at a time and encoding them
|
||||
* immediately.
|
||||
*/
|
||||
bool ListFilesResponse_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field)
|
||||
{
|
||||
PB_UNUSED(istream);
|
||||
if (ostream != NULL && field->tag == ListFilesResponse_file_tag)
|
||||
{
|
||||
DIR *dir = *(DIR**)field->pData;
|
||||
struct dirent *file;
|
||||
FileInfo fileinfo = {};
|
||||
|
||||
while ((file = readdir(dir)) != NULL)
|
||||
{
|
||||
fileinfo.inode = file->d_ino;
|
||||
strncpy(fileinfo.name, file->d_name, sizeof(fileinfo.name));
|
||||
fileinfo.name[sizeof(fileinfo.name) - 1] = '\0';
|
||||
|
||||
/* This encodes the header for the field, based on the constant info
|
||||
* from pb_field_t. */
|
||||
if (!pb_encode_tag_for_field(ostream, field))
|
||||
return false;
|
||||
|
||||
/* This encodes the data for the field, based on our FileInfo structure. */
|
||||
if (!pb_encode_submessage(ostream, FileInfo_fields, &fileinfo))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Because the main program uses pb_encode_delimited(), this callback will be
|
||||
* called twice. Rewind the directory for the next call. */
|
||||
rewinddir(dir);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Handle one arriving client connection.
|
||||
* Clients are expected to send a ListFilesRequest, terminated by a '0'.
|
||||
* Server will respond with a ListFilesResponse message.
|
||||
*/
|
||||
void handle_connection(int connfd)
|
||||
{
|
||||
DIR *directory = NULL;
|
||||
|
||||
/* Decode the message from the client and open the requested directory. */
|
||||
{
|
||||
ListFilesRequest request = {};
|
||||
pb_istream_t input = pb_istream_from_socket(connfd);
|
||||
|
||||
if (!pb_decode_delimited(&input, ListFilesRequest_fields, &request))
|
||||
{
|
||||
printf("Decode failed: %s\n", PB_GET_ERROR(&input));
|
||||
return;
|
||||
}
|
||||
|
||||
directory = opendir(request.path);
|
||||
printf("Listing directory: %s\n", request.path);
|
||||
}
|
||||
|
||||
/* List the files in the directory and transmit the response to client */
|
||||
{
|
||||
ListFilesResponse response = {};
|
||||
pb_ostream_t output = pb_ostream_from_socket(connfd);
|
||||
|
||||
if (directory == NULL)
|
||||
{
|
||||
perror("opendir");
|
||||
|
||||
/* Directory was not found, transmit error status */
|
||||
response.has_path_error = true;
|
||||
response.path_error = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Directory was found, transmit filenames */
|
||||
response.has_path_error = false;
|
||||
response.file = directory;
|
||||
}
|
||||
|
||||
if (!pb_encode_delimited(&output, ListFilesResponse_fields, &response))
|
||||
{
|
||||
printf("Encoding failed: %s\n", PB_GET_ERROR(&output));
|
||||
}
|
||||
}
|
||||
|
||||
if (directory != NULL)
|
||||
closedir(directory);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int listenfd, connfd;
|
||||
struct sockaddr_in servaddr;
|
||||
int reuse = 1;
|
||||
|
||||
/* Listen on localhost:1234 for TCP connections */
|
||||
listenfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
|
||||
|
||||
memset(&servaddr, 0, sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
servaddr.sin_port = htons(1234);
|
||||
if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0)
|
||||
{
|
||||
perror("bind");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (listen(listenfd, 5) != 0)
|
||||
{
|
||||
perror("listen");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
/* Wait for a client */
|
||||
connfd = accept(listenfd, NULL, NULL);
|
||||
|
||||
if (connfd < 0)
|
||||
{
|
||||
perror("accept");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Got connection.\n");
|
||||
|
||||
handle_connection(connfd);
|
||||
|
||||
printf("Closing connection.\n");
|
||||
|
||||
close(connfd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
5
third_party/nanopb/examples/platformio/.gitignore
vendored
Normal file
5
third_party/nanopb/examples/platformio/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
.pio/
|
||||
.idea/
|
||||
cmake-build-*/
|
||||
/CMakeLists.txt
|
||||
CMakeListsPrivate.txt
|
48
third_party/nanopb/examples/platformio/platformio.ini
vendored
Normal file
48
third_party/nanopb/examples/platformio/platformio.ini
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
;
|
||||
; You can setup `custom_nanopb_protos` `nanopb_options` vars to generate code from proto files
|
||||
;
|
||||
; Generator will use next folders:
|
||||
;
|
||||
; `$BUILD_DIR/nanopb/generated-src` - `*.pb.h` and `*.pb.c` files
|
||||
; `$BUILD_DIR/nanopb/md5` - MD5 files to track changes in source .proto/.options
|
||||
;
|
||||
; Compiled `.pb.o` files will be located under `$BUILD_DIR/nanopb/generated-build`
|
||||
;
|
||||
; Example:
|
||||
|
||||
[env:pio_with_options]
|
||||
platform = native
|
||||
lib_deps = Nanopb
|
||||
|
||||
src_filter =
|
||||
+<pio_with_options.c>
|
||||
|
||||
; All path are relative to the `$PROJECT_DIR`
|
||||
custom_nanopb_protos =
|
||||
+<proto/pio_with_options.proto>
|
||||
custom_nanopb_options =
|
||||
--error-on-unmatched
|
||||
|
||||
[env:pio_without_options]
|
||||
platform = native
|
||||
lib_deps = Nanopb
|
||||
|
||||
src_filter =
|
||||
+<pio_without_options.c>
|
||||
|
||||
; All path are relative to the `$PROJECT_DIR`
|
||||
custom_nanopb_protos =
|
||||
+<proto/pio_without_options.proto>
|
||||
|
||||
|
||||
[env:pio_esp32_idf]
|
||||
platform = espressif32
|
||||
board = firebeetle32
|
||||
framework = espidf
|
||||
lib_deps = Nanopb
|
||||
|
||||
; Warning: the 'src_filter' option cannot be used with ESP-IDF. Select source files to build in the project CMakeLists.txt file.
|
||||
; So, we specified source files in src/CMakeLists.txt
|
||||
|
||||
custom_nanopb_protos =
|
||||
+<proto/pio_without_options.proto>
|
1
third_party/nanopb/examples/platformio/proto/pio_with_options.options
vendored
Normal file
1
third_party/nanopb/examples/platformio/proto/pio_with_options.options
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
TestMessageWithOptions.str max_size:16
|
5
third_party/nanopb/examples/platformio/proto/pio_with_options.proto
vendored
Normal file
5
third_party/nanopb/examples/platformio/proto/pio_with_options.proto
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
syntax = "proto3";
|
||||
|
||||
message TestMessageWithOptions {
|
||||
string str = 1;
|
||||
}
|
5
third_party/nanopb/examples/platformio/proto/pio_without_options.proto
vendored
Normal file
5
third_party/nanopb/examples/platformio/proto/pio_without_options.proto
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
syntax = "proto3";
|
||||
|
||||
message TestMessageWithoutOptions {
|
||||
int32 number = 1;
|
||||
}
|
34
third_party/nanopb/examples/platformio/src/pio_esp32_idf.c
vendored
Normal file
34
third_party/nanopb/examples/platformio/src/pio_esp32_idf.c
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include "pb_encode.h"
|
||||
#include "pb_decode.h"
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include "pio_without_options.pb.h"
|
||||
|
||||
void app_main() {
|
||||
int status = 0;
|
||||
|
||||
uint8_t buffer[256];
|
||||
pb_ostream_t ostream;
|
||||
pb_istream_t istream;
|
||||
size_t written;
|
||||
|
||||
TestMessageWithoutOptions original = TestMessageWithoutOptions_init_zero;
|
||||
original.number = 45;
|
||||
|
||||
ostream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
|
||||
TEST(pb_encode(&ostream, &TestMessageWithoutOptions_msg, &original));
|
||||
|
||||
written = ostream.bytes_written;
|
||||
|
||||
istream = pb_istream_from_buffer(buffer, written);
|
||||
|
||||
TestMessageWithoutOptions decoded = TestMessageWithoutOptions_init_zero;
|
||||
|
||||
TEST(pb_decode(&istream, &TestMessageWithoutOptions_msg, &decoded));
|
||||
|
||||
TEST(decoded.number == 45);
|
||||
|
||||
return status;
|
||||
}
|
35
third_party/nanopb/examples/platformio/src/pio_with_options.c
vendored
Normal file
35
third_party/nanopb/examples/platformio/src/pio_with_options.c
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include "pb_encode.h"
|
||||
#include "pb_decode.h"
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include "pio_with_options.pb.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
int status = 0;
|
||||
|
||||
uint8_t buffer[256];
|
||||
pb_ostream_t ostream;
|
||||
pb_istream_t istream;
|
||||
size_t written;
|
||||
|
||||
TestMessageWithOptions original = TestMessageWithOptions_init_zero;
|
||||
strcpy(original.str,"Hello");
|
||||
|
||||
ostream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
|
||||
TEST(pb_encode(&ostream, &TestMessageWithOptions_msg, &original));
|
||||
|
||||
written = ostream.bytes_written;
|
||||
|
||||
istream = pb_istream_from_buffer(buffer, written);
|
||||
|
||||
TestMessageWithOptions decoded = TestMessageWithOptions_init_zero;
|
||||
|
||||
TEST(pb_decode(&istream, &TestMessageWithOptions_msg, &decoded));
|
||||
|
||||
TEST(strcmp(decoded.str,"Hello") == 0);
|
||||
|
||||
return status;
|
||||
}
|
35
third_party/nanopb/examples/platformio/src/pio_without_options.c
vendored
Normal file
35
third_party/nanopb/examples/platformio/src/pio_without_options.c
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include "pb_encode.h"
|
||||
#include "pb_decode.h"
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include "pio_without_options.pb.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
int status = 0;
|
||||
|
||||
uint8_t buffer[256];
|
||||
pb_ostream_t ostream;
|
||||
pb_istream_t istream;
|
||||
size_t written;
|
||||
|
||||
TestMessageWithoutOptions original = TestMessageWithoutOptions_init_zero;
|
||||
original.number = 45;
|
||||
|
||||
ostream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
|
||||
TEST(pb_encode(&ostream, &TestMessageWithoutOptions_msg, &original));
|
||||
|
||||
written = ostream.bytes_written;
|
||||
|
||||
istream = pb_istream_from_buffer(buffer, written);
|
||||
|
||||
TestMessageWithoutOptions decoded = TestMessageWithoutOptions_init_zero;
|
||||
|
||||
TEST(pb_decode(&istream, &TestMessageWithoutOptions_msg, &decoded));
|
||||
|
||||
TEST(decoded.number == 45);
|
||||
|
||||
return status;
|
||||
}
|
9
third_party/nanopb/examples/platformio/src/test.h
vendored
Normal file
9
third_party/nanopb/examples/platformio/src/test.h
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#define TEST(x) \
|
||||
if (!(x)) { \
|
||||
fprintf(stderr, "\033[31;1mFAILED:\033[22;39m %s:%d %s\n", __FILE__, __LINE__, #x); \
|
||||
status = 1; \
|
||||
} else { \
|
||||
printf("\033[32;1mOK:\033[22;39m %s\n", #x); \
|
||||
}
|
22
third_party/nanopb/examples/simple/Makefile
vendored
Normal file
22
third_party/nanopb/examples/simple/Makefile
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Include the nanopb provided Makefile rules
|
||||
include ../../extra/nanopb.mk
|
||||
|
||||
# Compiler flags to enable all warnings & debug info
|
||||
CFLAGS = -Wall -Werror -g -O0
|
||||
CFLAGS += "-I$(NANOPB_DIR)"
|
||||
|
||||
# C source code files that are required
|
||||
CSRC = simple.c # The main program
|
||||
CSRC += simple.pb.c # The compiled protocol definition
|
||||
CSRC += $(NANOPB_DIR)/pb_encode.c # The nanopb encoder
|
||||
CSRC += $(NANOPB_DIR)/pb_decode.c # The nanopb decoder
|
||||
CSRC += $(NANOPB_DIR)/pb_common.c # The nanopb common parts
|
||||
|
||||
# Build rule for the main program
|
||||
simple: $(CSRC)
|
||||
$(CC) $(CFLAGS) -osimple $(CSRC)
|
||||
|
||||
# Build rule for the protocol
|
||||
simple.pb.c: simple.proto
|
||||
$(PROTOC) $(PROTOC_OPTS) --nanopb_out=. simple.proto
|
||||
|
29
third_party/nanopb/examples/simple/README.txt
vendored
Normal file
29
third_party/nanopb/examples/simple/README.txt
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
Nanopb example "simple"
|
||||
=======================
|
||||
|
||||
This example demonstrates the very basic use of nanopb. It encodes and
|
||||
decodes a simple message.
|
||||
|
||||
The code uses four different API functions:
|
||||
|
||||
* pb_ostream_from_buffer() to declare the output buffer that is to be used
|
||||
* pb_encode() to encode a message
|
||||
* pb_istream_from_buffer() to declare the input buffer that is to be used
|
||||
* pb_decode() to decode a message
|
||||
|
||||
Example usage
|
||||
-------------
|
||||
|
||||
On Linux, simply type "make" to build the example. After that, you can
|
||||
run it with the command: ./simple
|
||||
|
||||
On other platforms, you first have to compile the protocol definition using
|
||||
the following command::
|
||||
|
||||
../../generator-bin/protoc --nanopb_out=. simple.proto
|
||||
|
||||
After that, add the following five files to your project and compile:
|
||||
|
||||
simple.c simple.pb.c pb_encode.c pb_decode.c pb_common.c
|
||||
|
||||
|
71
third_party/nanopb/examples/simple/simple.c
vendored
Normal file
71
third_party/nanopb/examples/simple/simple.c
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
#include <stdio.h>
|
||||
#include <pb_encode.h>
|
||||
#include <pb_decode.h>
|
||||
#include "simple.pb.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
/* This is the buffer where we will store our message. */
|
||||
uint8_t buffer[128];
|
||||
size_t message_length;
|
||||
bool status;
|
||||
|
||||
/* Encode our message */
|
||||
{
|
||||
/* Allocate space on the stack to store the message data.
|
||||
*
|
||||
* Nanopb generates simple struct definitions for all the messages.
|
||||
* - check out the contents of simple.pb.h!
|
||||
* It is a good idea to always initialize your structures
|
||||
* so that you do not have garbage data from RAM in there.
|
||||
*/
|
||||
SimpleMessage message = SimpleMessage_init_zero;
|
||||
|
||||
/* Create a stream that will write to our buffer. */
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
|
||||
/* Fill in the lucky number */
|
||||
message.lucky_number = 13;
|
||||
|
||||
/* Now we are ready to encode the message! */
|
||||
status = pb_encode(&stream, SimpleMessage_fields, &message);
|
||||
message_length = stream.bytes_written;
|
||||
|
||||
/* Then just check for any errors.. */
|
||||
if (!status)
|
||||
{
|
||||
printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we could transmit the message over network, store it in a file or
|
||||
* wrap it to a pigeon's leg.
|
||||
*/
|
||||
|
||||
/* But because we are lazy, we will just decode it immediately. */
|
||||
|
||||
{
|
||||
/* Allocate space for the decoded message. */
|
||||
SimpleMessage message = SimpleMessage_init_zero;
|
||||
|
||||
/* Create a stream that reads from the buffer. */
|
||||
pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
|
||||
|
||||
/* Now we are ready to decode the message. */
|
||||
status = pb_decode(&stream, SimpleMessage_fields, &message);
|
||||
|
||||
/* Check for errors... */
|
||||
if (!status)
|
||||
{
|
||||
printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Print the data contained in the message. */
|
||||
printf("Your lucky number was %d!\n", (int)message.lucky_number);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
9
third_party/nanopb/examples/simple/simple.proto
vendored
Normal file
9
third_party/nanopb/examples/simple/simple.proto
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
// A very simple protocol definition, consisting of only
|
||||
// one message.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
message SimpleMessage {
|
||||
required int32 lucky_number = 1;
|
||||
}
|
||||
|
20
third_party/nanopb/examples/using_union_messages/Makefile
vendored
Normal file
20
third_party/nanopb/examples/using_union_messages/Makefile
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Include the nanopb provided Makefile rules
|
||||
include ../../extra/nanopb.mk
|
||||
|
||||
# Compiler flags to enable all warnings & debug info
|
||||
CFLAGS = -ansi -Wall -Werror -g -O0
|
||||
CFLAGS += -I$(NANOPB_DIR)
|
||||
|
||||
all: encode decode
|
||||
./encode 1 | ./decode
|
||||
./encode 2 | ./decode
|
||||
./encode 3 | ./decode
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
clean:
|
||||
rm -f encode unionproto.pb.h unionproto.pb.c
|
||||
|
||||
%: %.c unionproto.pb.c
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(NANOPB_CORE)
|
||||
|
55
third_party/nanopb/examples/using_union_messages/README.txt
vendored
Normal file
55
third_party/nanopb/examples/using_union_messages/README.txt
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
Nanopb example "using_union_messages"
|
||||
=====================================
|
||||
|
||||
Union messages is a common technique in Google Protocol Buffers used to
|
||||
represent a group of messages, only one of which is passed at a time.
|
||||
It is described in Google's documentation:
|
||||
https://developers.google.com/protocol-buffers/docs/techniques#union
|
||||
|
||||
This directory contains an example on how to encode and decode union messages
|
||||
with minimal memory usage. Usually, nanopb would allocate space to store
|
||||
all of the possible messages at the same time, even though at most one of
|
||||
them will be used at a time.
|
||||
|
||||
By using some of the lower level nanopb APIs, we can manually generate the
|
||||
top level message, so that we only need to allocate the one submessage that
|
||||
we actually want. Similarly when decoding, we can manually read the tag of
|
||||
the top level message, and only then allocate the memory for the submessage
|
||||
after we already know its type.
|
||||
|
||||
NOTE: There is a newer protobuf feature called `oneof` that is also supported
|
||||
by nanopb. It might be a better option for new code.
|
||||
|
||||
|
||||
Example usage
|
||||
-------------
|
||||
|
||||
Type `make` to run the example. It will build it and run commands like
|
||||
following:
|
||||
|
||||
./encode 1 | ./decode
|
||||
Got MsgType1: 42
|
||||
./encode 2 | ./decode
|
||||
Got MsgType2: true
|
||||
./encode 3 | ./decode
|
||||
Got MsgType3: 3 1415
|
||||
|
||||
This simply demonstrates that the "decode" program has correctly identified
|
||||
the type of the received message, and managed to decode it.
|
||||
|
||||
|
||||
Details of implementation
|
||||
-------------------------
|
||||
|
||||
unionproto.proto contains the protocol used in the example. It consists of
|
||||
three messages: MsgType1, MsgType2 and MsgType3, which are collected together
|
||||
into UnionMessage.
|
||||
|
||||
encode.c takes one command line argument, which should be a number 1-3. It
|
||||
then fills in and encodes the corresponding message, and writes it to stdout.
|
||||
|
||||
decode.c reads a UnionMessage from stdin. Then it calls the function
|
||||
decode_unionmessage_type() to determine the type of the message. After that,
|
||||
the corresponding message is decoded and the contents of it printed to the
|
||||
screen.
|
||||
|
95
third_party/nanopb/examples/using_union_messages/decode.c
vendored
Normal file
95
third_party/nanopb/examples/using_union_messages/decode.c
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
/* This program reads a message from stdin, detects its type and decodes it.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pb_decode.h>
|
||||
#include <pb_common.h>
|
||||
#include "unionproto.pb.h"
|
||||
|
||||
/* This function reads manually the first tag from the stream and finds the
|
||||
* corresponding message type. It doesn't yet decode the actual message.
|
||||
*
|
||||
* Returns a pointer to the MsgType_fields array, as an identifier for the
|
||||
* message type. Returns null if the tag is of unknown type or an error occurs.
|
||||
*/
|
||||
const pb_msgdesc_t* decode_unionmessage_type(pb_istream_t *stream)
|
||||
{
|
||||
pb_wire_type_t wire_type;
|
||||
uint32_t tag;
|
||||
bool eof;
|
||||
|
||||
while (pb_decode_tag(stream, &wire_type, &tag, &eof))
|
||||
{
|
||||
if (wire_type == PB_WT_STRING)
|
||||
{
|
||||
pb_field_iter_t iter;
|
||||
if (pb_field_iter_begin(&iter, UnionMessage_fields, NULL) &&
|
||||
pb_field_iter_find(&iter, tag))
|
||||
{
|
||||
/* Found our field. */
|
||||
return iter.submsg_desc;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wasn't our field.. */
|
||||
pb_skip_field(stream, wire_type);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool decode_unionmessage_contents(pb_istream_t *stream, const pb_msgdesc_t *messagetype, void *dest_struct)
|
||||
{
|
||||
pb_istream_t substream;
|
||||
bool status;
|
||||
if (!pb_make_string_substream(stream, &substream))
|
||||
return false;
|
||||
|
||||
status = pb_decode(&substream, messagetype, dest_struct);
|
||||
pb_close_string_substream(stream, &substream);
|
||||
return status;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
/* Read the data into buffer */
|
||||
uint8_t buffer[512];
|
||||
size_t count = fread(buffer, 1, sizeof(buffer), stdin);
|
||||
pb_istream_t stream = pb_istream_from_buffer(buffer, count);
|
||||
|
||||
const pb_msgdesc_t *type = decode_unionmessage_type(&stream);
|
||||
bool status = false;
|
||||
|
||||
if (type == MsgType1_fields)
|
||||
{
|
||||
MsgType1 msg = {};
|
||||
status = decode_unionmessage_contents(&stream, MsgType1_fields, &msg);
|
||||
printf("Got MsgType1: %d\n", msg.value);
|
||||
}
|
||||
else if (type == MsgType2_fields)
|
||||
{
|
||||
MsgType2 msg = {};
|
||||
status = decode_unionmessage_contents(&stream, MsgType2_fields, &msg);
|
||||
printf("Got MsgType2: %s\n", msg.value ? "true" : "false");
|
||||
}
|
||||
else if (type == MsgType3_fields)
|
||||
{
|
||||
MsgType3 msg = {};
|
||||
status = decode_unionmessage_contents(&stream, MsgType3_fields, &msg);
|
||||
printf("Got MsgType3: %d %d\n", msg.value1, msg.value2);
|
||||
}
|
||||
|
||||
if (!status)
|
||||
{
|
||||
printf("Decode failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
90
third_party/nanopb/examples/using_union_messages/encode.c
vendored
Normal file
90
third_party/nanopb/examples/using_union_messages/encode.c
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
/* This program takes a command line argument and encodes a message in
|
||||
* one of MsgType1, MsgType2 or MsgType3.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pb_encode.h>
|
||||
#include <pb_common.h>
|
||||
#include "unionproto.pb.h"
|
||||
|
||||
/* This function is the core of the union encoding process. It handles
|
||||
* the top-level pb_field_t array manually, in order to encode a correct
|
||||
* field tag before the message. The pointer to MsgType_fields array is
|
||||
* used as an unique identifier for the message type.
|
||||
*/
|
||||
bool encode_unionmessage(pb_ostream_t *stream, const pb_msgdesc_t *messagetype, void *message)
|
||||
{
|
||||
pb_field_iter_t iter;
|
||||
|
||||
if (!pb_field_iter_begin(&iter, UnionMessage_fields, message))
|
||||
return false;
|
||||
|
||||
do
|
||||
{
|
||||
if (iter.submsg_desc == messagetype)
|
||||
{
|
||||
/* This is our field, encode the message using it. */
|
||||
if (!pb_encode_tag_for_field(stream, &iter))
|
||||
return false;
|
||||
|
||||
return pb_encode_submessage(stream, messagetype, message);
|
||||
}
|
||||
} while (pb_field_iter_next(&iter));
|
||||
|
||||
/* Didn't find the field for messagetype */
|
||||
return false;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s (1|2|3)\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t buffer[512];
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
|
||||
bool status = false;
|
||||
int msgtype = atoi(argv[1]);
|
||||
if (msgtype == 1)
|
||||
{
|
||||
/* Send message of type 1 */
|
||||
MsgType1 msg = {42};
|
||||
status = encode_unionmessage(&stream, MsgType1_fields, &msg);
|
||||
}
|
||||
else if (msgtype == 2)
|
||||
{
|
||||
/* Send message of type 2 */
|
||||
MsgType2 msg = {true};
|
||||
status = encode_unionmessage(&stream, MsgType2_fields, &msg);
|
||||
}
|
||||
else if (msgtype == 3)
|
||||
{
|
||||
/* Send message of type 3 */
|
||||
MsgType3 msg = {3, 1415};
|
||||
status = encode_unionmessage(&stream, MsgType3_fields, &msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unknown message type: %d\n", msgtype);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (!status)
|
||||
{
|
||||
fprintf(stderr, "Encoding failed!\n");
|
||||
return 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
fwrite(buffer, 1, stream.bytes_written, stdout);
|
||||
return 0; /* Success */
|
||||
}
|
||||
}
|
||||
|
||||
|
32
third_party/nanopb/examples/using_union_messages/unionproto.proto
vendored
Normal file
32
third_party/nanopb/examples/using_union_messages/unionproto.proto
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
// This is an example of how to handle 'union' style messages
|
||||
// with nanopb, without allocating memory for all the message types.
|
||||
//
|
||||
// There is no official type in Protocol Buffers for describing unions,
|
||||
// but they are commonly implemented by filling out exactly one of
|
||||
// several optional fields.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
message MsgType1
|
||||
{
|
||||
required int32 value = 1;
|
||||
}
|
||||
|
||||
message MsgType2
|
||||
{
|
||||
required bool value = 1;
|
||||
}
|
||||
|
||||
message MsgType3
|
||||
{
|
||||
required int32 value1 = 1;
|
||||
required int32 value2 = 2;
|
||||
}
|
||||
|
||||
message UnionMessage
|
||||
{
|
||||
optional MsgType1 msg1 = 1;
|
||||
optional MsgType2 msg2 = 2;
|
||||
optional MsgType3 msg3 = 3;
|
||||
}
|
||||
|
11
third_party/nanopb/extra/nanopb-config-version.cmake.in
vendored
Normal file
11
third_party/nanopb/extra/nanopb-config-version.cmake.in
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
set(PACKAGE_VERSION "@nanopb_VERSION@")
|
||||
|
||||
# Check whether the requested PACKAGE_FIND_VERSION is compatible
|
||||
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_EXACT TRUE)
|
||||
endif()
|
||||
endif()
|
1
third_party/nanopb/extra/nanopb-config.cmake
vendored
Normal file
1
third_party/nanopb/extra/nanopb-config.cmake
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
include(${CMAKE_CURRENT_LIST_DIR}/nanopb-targets.cmake)
|
40
third_party/nanopb/extra/nanopb.mk
vendored
Normal file
40
third_party/nanopb/extra/nanopb.mk
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
# This is an include file for Makefiles. It provides rules for building
|
||||
# .pb.c and .pb.h files out of .proto, as well the path to nanopb core.
|
||||
|
||||
# Path to the nanopb root directory
|
||||
NANOPB_DIR := $(patsubst %/,%,$(dir $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))))
|
||||
|
||||
# Files for the nanopb core
|
||||
NANOPB_CORE = $(NANOPB_DIR)/pb_encode.c $(NANOPB_DIR)/pb_decode.c $(NANOPB_DIR)/pb_common.c
|
||||
|
||||
# Check if we are running on Windows
|
||||
ifdef windir
|
||||
WINDOWS = 1
|
||||
endif
|
||||
ifdef WINDIR
|
||||
WINDOWS = 1
|
||||
endif
|
||||
|
||||
# Check whether to use binary version of nanopb_generator or the
|
||||
# system-supplied python interpreter.
|
||||
ifneq "$(wildcard $(NANOPB_DIR)/generator-bin)" ""
|
||||
# Binary package
|
||||
PROTOC = $(NANOPB_DIR)/generator-bin/protoc
|
||||
PROTOC_OPTS =
|
||||
else
|
||||
# Source only or git checkout
|
||||
PROTOC_OPTS =
|
||||
ifdef WINDOWS
|
||||
PROTOC = python $(NANOPB_DIR)/generator/protoc
|
||||
else
|
||||
PROTOC = $(NANOPB_DIR)/generator/protoc
|
||||
endif
|
||||
endif
|
||||
|
||||
# Rule for building .pb.c and .pb.h
|
||||
%.pb.c %.pb.h: %.proto %.options
|
||||
$(PROTOC) $(PROTOC_OPTS) --nanopb_out=. $<
|
||||
|
||||
%.pb.c %.pb.h: %.proto
|
||||
$(PROTOC) $(PROTOC_OPTS) --nanopb_out=. $<
|
||||
|
120
third_party/nanopb/extra/pb_syshdr.h
vendored
Normal file
120
third_party/nanopb/extra/pb_syshdr.h
vendored
Normal file
|
@ -0,0 +1,120 @@
|
|||
/* This is an example of a header file for platforms/compilers that do
|
||||
* not come with stdint.h/stddef.h/stdbool.h/string.h. To use it, define
|
||||
* PB_SYSTEM_HEADER as "pb_syshdr.h", including the quotes, and add the
|
||||
* extra folder to your include path.
|
||||
*
|
||||
* It is very likely that you will need to customize this file to suit
|
||||
* your platform. For any compiler that supports C99, this file should
|
||||
* not be necessary.
|
||||
*/
|
||||
|
||||
#ifndef _PB_SYSHDR_H_
|
||||
#define _PB_SYSHDR_H_
|
||||
|
||||
/* stdint.h subset */
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#else
|
||||
/* You will need to modify these to match the word size of your platform. */
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef signed long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
/* These are ok for most platforms, unless uint8_t is actually not available,
|
||||
* in which case you should give the smallest available type. */
|
||||
typedef int8_t int_least8_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
#endif
|
||||
|
||||
/* stddef.h subset */
|
||||
#ifdef HAVE_STDDEF_H
|
||||
#include <stddef.h>
|
||||
#else
|
||||
|
||||
typedef uint32_t size_t;
|
||||
#define offsetof(st, m) ((size_t)(&((st *)0)->m))
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* stdbool.h subset */
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
|
||||
#ifndef __cplusplus
|
||||
typedef int bool;
|
||||
#define false 0
|
||||
#define true 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* stdlib.h subset */
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
void *realloc(void *ptr, size_t size);
|
||||
void free(void *ptr);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* string.h subset */
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#else
|
||||
|
||||
/* Implementations are from the Public Domain C Library (PDCLib). */
|
||||
static size_t strlen( const char * s )
|
||||
{
|
||||
size_t rc = 0;
|
||||
while ( s[rc] )
|
||||
{
|
||||
++rc;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void * memcpy( void *s1, const void *s2, size_t n )
|
||||
{
|
||||
char * dest = (char *) s1;
|
||||
const char * src = (const char *) s2;
|
||||
while ( n-- )
|
||||
{
|
||||
*dest++ = *src++;
|
||||
}
|
||||
return s1;
|
||||
}
|
||||
|
||||
static void * memset( void * s, int c, size_t n )
|
||||
{
|
||||
unsigned char * p = (unsigned char *) s;
|
||||
while ( n-- )
|
||||
{
|
||||
*p++ = (unsigned char) c;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* limits.h subset */
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#else
|
||||
#define CHAR_BIT 8
|
||||
#endif
|
||||
|
||||
#endif
|
20
third_party/nanopb/extra/poetry/poetry_build.sh
vendored
Executable file
20
third_party/nanopb/extra/poetry/poetry_build.sh
vendored
Executable file
|
@ -0,0 +1,20 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
rm -rf build
|
||||
mkdir build
|
||||
mkdir -p dist
|
||||
|
||||
(cd "$(git rev-parse --show-toplevel)"; git archive HEAD) > build/tmp.tar
|
||||
cd build
|
||||
ln -s ../dist .
|
||||
|
||||
mkdir nanopb
|
||||
tar xf tmp.tar README.md generator
|
||||
mv generator nanopb/
|
||||
touch nanopb/__init__.py nanopb/generator/__init__.py
|
||||
make -C nanopb/generator/proto
|
||||
cp ../pyproject.toml .
|
||||
sed -i -e 's/\(version =.*\)-dev.*/\1-dev'$(git rev-list HEAD --count)'"/' pyproject.toml
|
||||
poetry build
|
31
third_party/nanopb/extra/poetry/pyproject.toml
vendored
Normal file
31
third_party/nanopb/extra/poetry/pyproject.toml
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
[tool.poetry]
|
||||
name = "nanopb"
|
||||
version = "0.4.6"
|
||||
description = "Nanopb is a small code-size Protocol Buffers implementation in ansi C. It is especially suitable for use in microcontrollers, but fits any memory restricted system."
|
||||
authors = ["Petteri Aimonen <jpa@npb.mail.kapsi.fi>"]
|
||||
license = "Zlib"
|
||||
repository = "https://github.com/nanopb/nanopb/"
|
||||
readme = "README.md"
|
||||
homepage = "https://jpa.kapsi.fi/nanopb/"
|
||||
documentation = "https://jpa.kapsi.fi/nanopb/docs/index.html"
|
||||
keywords = ["protobuf", "protoc"]
|
||||
classifiers = ["Topic :: Software Development :: Build Tools"]
|
||||
include = ["nanopb/**/*", "nanopb/__init__.py"]
|
||||
|
||||
[tool.poetry.scripts]
|
||||
nanopb_generator = "nanopb.generator.nanopb_generator:main_cli"
|
||||
protoc-gen-nanopb = "nanopb.generator.nanopb_generator:main_plugin"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=2.7"
|
||||
protobuf = ">=3.19"
|
||||
grpcio-tools = ">=1.46.0"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
|
||||
[tool.poetry.extras]
|
||||
grpcio-tools = ["grpcio-tools"]
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry>=0.12"]
|
||||
build-backend = "poetry.masonry.api"
|
2384
third_party/nanopb/generator/nanopb_generator.py
vendored
Executable file
2384
third_party/nanopb/generator/nanopb_generator.py
vendored
Executable file
File diff suppressed because it is too large
Load diff
13
third_party/nanopb/generator/nanopb_generator.py2
vendored
Executable file
13
third_party/nanopb/generator/nanopb_generator.py2
vendored
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env python2
|
||||
# This file is a wrapper around nanopb_generator.py in case you want to run
|
||||
# it with Python 2 instead of default Python 3. This only exists for backwards
|
||||
# compatibility, do not use for new projects.
|
||||
|
||||
from nanopb_generator import *
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Check if we are running as a plugin under protoc
|
||||
if 'protoc-gen-' in sys.argv[0] or '--protoc-plugin' in sys.argv:
|
||||
main_plugin()
|
||||
else:
|
||||
main_cli()
|
154
third_party/nanopb/generator/platformio_generator.py
vendored
Normal file
154
third_party/nanopb/generator/platformio_generator.py
vendored
Normal file
|
@ -0,0 +1,154 @@
|
|||
import os
|
||||
import hashlib
|
||||
import pathlib
|
||||
from platformio import fs
|
||||
|
||||
Import("env")
|
||||
|
||||
try:
|
||||
import protobuf
|
||||
except ImportError:
|
||||
env.Execute(
|
||||
env.VerboseAction(
|
||||
# We need to speicify protobuf version. In other case got next (on Ubuntu 20.04):
|
||||
# Requirement already satisfied: protobuf in /usr/lib/python3/dist-packages (3.6.1)
|
||||
'$PYTHONEXE -m pip install "protobuf>=3.19.1"',
|
||||
"Installing Protocol Buffers dependencies",
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
import grpc_tools.protoc
|
||||
except ImportError:
|
||||
env.Execute(
|
||||
env.VerboseAction(
|
||||
'$PYTHONEXE -m pip install "grpcio-tools>=1.43.0"',
|
||||
"Installing GRPC dependencies",
|
||||
)
|
||||
)
|
||||
|
||||
nanopb_root = os.path.join(os.getcwd(), '..')
|
||||
|
||||
project_dir = env.subst("$PROJECT_DIR")
|
||||
build_dir = env.subst("$BUILD_DIR")
|
||||
|
||||
generated_src_dir = os.path.join(build_dir, 'nanopb', 'generated-src')
|
||||
generated_build_dir = os.path.join(build_dir, 'nanopb', 'generated-build')
|
||||
md5_dir = os.path.join(build_dir, 'nanopb', 'md5')
|
||||
|
||||
nanopb_protos = env.GetProjectOption("custom_nanopb_protos", "")
|
||||
nanopb_plugin_options = env.GetProjectOption("custom_nanopb_options", "")
|
||||
|
||||
if not nanopb_protos:
|
||||
print("[nanopb] No generation needed.")
|
||||
else:
|
||||
if isinstance(nanopb_plugin_options, (list, tuple)):
|
||||
nanopb_plugin_options = " ".join(nanopb_plugin_options)
|
||||
|
||||
nanopb_plugin_options = nanopb_plugin_options.split()
|
||||
|
||||
protos_files = fs.match_src_files(project_dir, nanopb_protos)
|
||||
if not len(protos_files):
|
||||
print("[nanopb] ERROR: No files matched pattern:")
|
||||
print(f"custom_nanopb_protos: {nanopb_protos}")
|
||||
exit(1)
|
||||
|
||||
protoc_generator = os.path.join(nanopb_root, 'generator', 'protoc')
|
||||
|
||||
nanopb_options = ""
|
||||
nanopb_options += f" --nanopb_out={generated_src_dir}"
|
||||
for opt in nanopb_plugin_options:
|
||||
nanopb_options += (" --nanopb_opt=" + opt)
|
||||
|
||||
try:
|
||||
os.makedirs(generated_src_dir)
|
||||
except FileExistsError:
|
||||
pass
|
||||
|
||||
try:
|
||||
os.makedirs(md5_dir)
|
||||
except FileExistsError:
|
||||
pass
|
||||
|
||||
# Collect include dirs based on
|
||||
proto_include_dirs = set()
|
||||
for proto_file in protos_files:
|
||||
proto_file_abs = os.path.join(project_dir, proto_file)
|
||||
proto_dir = os.path.dirname(proto_file_abs)
|
||||
proto_include_dirs.add(proto_dir)
|
||||
|
||||
for proto_include_dir in proto_include_dirs:
|
||||
nanopb_options += (" --proto_path=" + proto_include_dir)
|
||||
nanopb_options += (" --nanopb_opt=-I" + proto_include_dir)
|
||||
|
||||
for proto_file in protos_files:
|
||||
proto_file_abs = os.path.join(project_dir, proto_file)
|
||||
|
||||
proto_file_path_abs = os.path.dirname(proto_file_abs)
|
||||
proto_file_basename = os.path.basename(proto_file_abs)
|
||||
proto_file_without_ext = os.path.splitext(proto_file_basename)[0]
|
||||
|
||||
proto_file_md5_abs = os.path.join(md5_dir, proto_file_basename + '.md5')
|
||||
proto_file_current_md5 = hashlib.md5(pathlib.Path(proto_file_abs).read_bytes()).hexdigest()
|
||||
|
||||
options_file = proto_file_without_ext + ".options"
|
||||
options_file_abs = os.path.join(proto_file_path_abs, options_file)
|
||||
options_file_md5_abs = None
|
||||
options_file_current_md5 = None
|
||||
if pathlib.Path(options_file_abs).exists():
|
||||
options_file_md5_abs = os.path.join(md5_dir, options_file + '.md5')
|
||||
options_file_current_md5 = hashlib.md5(pathlib.Path(options_file_abs).read_bytes()).hexdigest()
|
||||
else:
|
||||
options_file = None
|
||||
|
||||
header_file = proto_file_without_ext + ".pb.h"
|
||||
source_file = proto_file_without_ext + ".pb.c"
|
||||
|
||||
header_file_abs = os.path.join(generated_src_dir, source_file)
|
||||
source_file_abs = os.path.join(generated_src_dir, header_file)
|
||||
|
||||
need_generate = False
|
||||
|
||||
# Check proto file md5
|
||||
try:
|
||||
last_md5 = pathlib.Path(proto_file_md5_abs).read_text()
|
||||
if last_md5 != proto_file_current_md5:
|
||||
need_generate = True
|
||||
except FileNotFoundError:
|
||||
need_generate = True
|
||||
|
||||
if options_file:
|
||||
# Check options file md5
|
||||
try:
|
||||
last_md5 = pathlib.Path(options_file_md5_abs).read_text()
|
||||
if last_md5 != options_file_current_md5:
|
||||
need_generate = True
|
||||
except FileNotFoundError:
|
||||
need_generate = True
|
||||
|
||||
options_info = f"{options_file}" if options_file else "no options"
|
||||
|
||||
if not need_generate:
|
||||
print(f"[nanopb] Skipping '{proto_file}' ({options_info})")
|
||||
else:
|
||||
print(f"[nanopb] Processing '{proto_file}' ({options_info})")
|
||||
cmd = protoc_generator + " " + nanopb_options + " " + proto_file_basename
|
||||
result = env.Execute(cmd)
|
||||
if result != 0:
|
||||
print(f"[nanopb] ERROR: ({result}) processing cmd: '{cmd}'")
|
||||
exit(1)
|
||||
pathlib.Path(proto_file_md5_abs).write_text(proto_file_current_md5)
|
||||
if options_file:
|
||||
pathlib.Path(options_file_md5_abs).write_text(options_file_current_md5)
|
||||
|
||||
#
|
||||
# Add generated includes and sources to build environment
|
||||
#
|
||||
env.Append(CPPPATH=[generated_src_dir])
|
||||
|
||||
# Fix for ESP32 ESP-IDF https://github.com/nanopb/nanopb/issues/734#issuecomment-1001544447
|
||||
global_env = DefaultEnvironment()
|
||||
already_called_env_name = "_PROTOBUF_GENERATOR_ALREADY_CALLED_" + env['PIOENV'].replace("-", "_")
|
||||
if not global_env.get(already_called_env_name, False):
|
||||
env.BuildSources(generated_build_dir, generated_src_dir)
|
||||
global_env[already_called_env_name] = True
|
10
third_party/nanopb/generator/proto/Makefile
vendored
Normal file
10
third_party/nanopb/generator/proto/Makefile
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
PROTOC?=../protoc
|
||||
|
||||
all: nanopb_pb2.py
|
||||
|
||||
%_pb2.py: %.proto
|
||||
$(PROTOC) --python_out=. $<
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm nanopb_pb2.py
|
50
third_party/nanopb/generator/proto/__init__.py
vendored
Normal file
50
third_party/nanopb/generator/proto/__init__.py
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
'''This file automatically rebuilds the proto definitions for Python.'''
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
import pkg_resources
|
||||
|
||||
from ._utils import has_grpcio_protoc, invoke_protoc, print_versions
|
||||
|
||||
dirname = os.path.dirname(__file__)
|
||||
protosrc = os.path.join(dirname, "nanopb.proto")
|
||||
protodst = os.path.join(dirname, "nanopb_pb2.py")
|
||||
rebuild = False
|
||||
|
||||
if os.path.isfile(protosrc):
|
||||
src_date = os.path.getmtime(protosrc)
|
||||
if not os.path.isfile(protodst) or os.path.getmtime(protodst) < src_date:
|
||||
rebuild = True
|
||||
|
||||
if not rebuild:
|
||||
try:
|
||||
from . import nanopb_pb2
|
||||
except AttributeError as e:
|
||||
rebuild = True
|
||||
sys.stderr.write("Failed to import nanopb_pb2.py: " + str(e) + "\n"
|
||||
"Will automatically attempt to rebuild this.\n"
|
||||
"Verify that python-protobuf and protoc versions match.\n")
|
||||
print_versions()
|
||||
|
||||
if rebuild:
|
||||
cmd = [
|
||||
"protoc",
|
||||
"--python_out={}".format(dirname),
|
||||
protosrc,
|
||||
"-I={}".format(dirname),
|
||||
]
|
||||
|
||||
if has_grpcio_protoc():
|
||||
# grpcio-tools has an extra CLI argument
|
||||
# from grpc.tools.protoc __main__ invocation.
|
||||
_builtin_proto_include = pkg_resources.resource_filename('grpc_tools', '_proto')
|
||||
|
||||
cmd.append("-I={}".format(_builtin_proto_include))
|
||||
try:
|
||||
invoke_protoc(argv=cmd)
|
||||
except:
|
||||
sys.stderr.write("Failed to build nanopb_pb2.py: " + ' '.join(cmd) + "\n")
|
||||
raise
|
||||
|
66
third_party/nanopb/generator/proto/_utils.py
vendored
Normal file
66
third_party/nanopb/generator/proto/_utils.py
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
import sys
|
||||
import subprocess
|
||||
import os.path
|
||||
|
||||
def has_grpcio_protoc():
|
||||
# type: () -> bool
|
||||
""" checks if grpcio-tools protoc is installed"""
|
||||
|
||||
try:
|
||||
import grpc_tools.protoc
|
||||
except ImportError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def invoke_protoc(argv):
|
||||
# type: (list) -> typing.Any
|
||||
"""
|
||||
Invoke protoc.
|
||||
|
||||
This routine will use grpcio-provided protoc if it exists,
|
||||
using system-installed protoc as a fallback.
|
||||
|
||||
Args:
|
||||
argv: protoc CLI invocation, first item must be 'protoc'
|
||||
"""
|
||||
|
||||
# Add current directory to include path if nothing else is specified
|
||||
if not [x for x in argv if x.startswith('-I')]:
|
||||
argv.append("-I.")
|
||||
|
||||
# Add default protoc include paths
|
||||
nanopb_include = os.path.dirname(os.path.abspath(__file__))
|
||||
argv.append('-I' + nanopb_include)
|
||||
|
||||
if has_grpcio_protoc():
|
||||
import grpc_tools.protoc as protoc
|
||||
import pkg_resources
|
||||
proto_include = pkg_resources.resource_filename('grpc_tools', '_proto')
|
||||
argv.append('-I' + proto_include)
|
||||
|
||||
return protoc.main(argv)
|
||||
else:
|
||||
return subprocess.call(argv)
|
||||
|
||||
def print_versions():
|
||||
try:
|
||||
if has_grpcio_protoc():
|
||||
import grpc_tools.protoc
|
||||
sys.stderr.write("Using grpcio-tools protoc from " + grpc_tools.protoc.__file__ + "\n")
|
||||
else:
|
||||
sys.stderr.write("Using protoc from system path\n")
|
||||
|
||||
invoke_protoc(['protoc', '--version'])
|
||||
except Exception as e:
|
||||
sys.stderr.write("Failed to determine protoc version: " + str(e) + "\n")
|
||||
|
||||
try:
|
||||
import google.protobuf
|
||||
sys.stderr.write("Using python-protobuf from " + google.protobuf.__file__ + "\n")
|
||||
sys.stderr.write("Python-protobuf version: " + google.protobuf.__version__ + "\n")
|
||||
except Exception as e:
|
||||
sys.stderr.write("Failed to determine python-protobuf version: " + str(e) + "\n")
|
||||
|
||||
if __name__ == '__main__':
|
||||
print_versions()
|
185
third_party/nanopb/generator/proto/nanopb.proto
vendored
Normal file
185
third_party/nanopb/generator/proto/nanopb.proto
vendored
Normal file
|
@ -0,0 +1,185 @@
|
|||
// Custom options for defining:
|
||||
// - Maximum size of string/bytes
|
||||
// - Maximum number of elements in array
|
||||
//
|
||||
// These are used by nanopb to generate statically allocable structures
|
||||
// for memory-limited environments.
|
||||
|
||||
syntax = "proto2";
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
option java_package = "fi.kapsi.koti.jpa.nanopb";
|
||||
|
||||
enum FieldType {
|
||||
FT_DEFAULT = 0; // Automatically decide field type, generate static field if possible.
|
||||
FT_CALLBACK = 1; // Always generate a callback field.
|
||||
FT_POINTER = 4; // Always generate a dynamically allocated field.
|
||||
FT_STATIC = 2; // Generate a static field or raise an exception if not possible.
|
||||
FT_IGNORE = 3; // Ignore the field completely.
|
||||
FT_INLINE = 5; // Legacy option, use the separate 'fixed_length' option instead
|
||||
}
|
||||
|
||||
enum IntSize {
|
||||
IS_DEFAULT = 0; // Default, 32/64bit based on type in .proto
|
||||
IS_8 = 8;
|
||||
IS_16 = 16;
|
||||
IS_32 = 32;
|
||||
IS_64 = 64;
|
||||
}
|
||||
|
||||
enum TypenameMangling {
|
||||
M_NONE = 0; // Default, no typename mangling
|
||||
M_STRIP_PACKAGE = 1; // Strip current package name
|
||||
M_FLATTEN = 2; // Only use last path component
|
||||
M_PACKAGE_INITIALS = 3; // Replace the package name by the initials
|
||||
}
|
||||
|
||||
enum DescriptorSize {
|
||||
DS_AUTO = 0; // Select minimal size based on field type
|
||||
DS_1 = 1; // 1 word; up to 15 byte fields, no arrays
|
||||
DS_2 = 2; // 2 words; up to 4095 byte fields, 4095 entry arrays
|
||||
DS_4 = 4; // 4 words; up to 2^32-1 byte fields, 2^16-1 entry arrays
|
||||
DS_8 = 8; // 8 words; up to 2^32-1 entry arrays
|
||||
}
|
||||
|
||||
// This is the inner options message, which basically defines options for
|
||||
// a field. When it is used in message or file scope, it applies to all
|
||||
// fields.
|
||||
message NanoPBOptions {
|
||||
// Allocated size for 'bytes' and 'string' fields.
|
||||
// For string fields, this should include the space for null terminator.
|
||||
optional int32 max_size = 1;
|
||||
|
||||
// Maximum length for 'string' fields. Setting this is equivalent
|
||||
// to setting max_size to a value of length+1.
|
||||
optional int32 max_length = 14;
|
||||
|
||||
// Allocated number of entries in arrays ('repeated' fields)
|
||||
optional int32 max_count = 2;
|
||||
|
||||
// Size of integer fields. Can save some memory if you don't need
|
||||
// full 32 bits for the value.
|
||||
optional IntSize int_size = 7 [default = IS_DEFAULT];
|
||||
|
||||
// Force type of field (callback or static allocation)
|
||||
optional FieldType type = 3 [default = FT_DEFAULT];
|
||||
|
||||
// Use long names for enums, i.e. EnumName_EnumValue.
|
||||
optional bool long_names = 4 [default = true];
|
||||
|
||||
// Add 'packed' attribute to generated structs.
|
||||
// Note: this cannot be used on CPUs that break on unaligned
|
||||
// accesses to variables.
|
||||
optional bool packed_struct = 5 [default = false];
|
||||
|
||||
// Add 'packed' attribute to generated enums.
|
||||
optional bool packed_enum = 10 [default = false];
|
||||
|
||||
// Skip this message
|
||||
optional bool skip_message = 6 [default = false];
|
||||
|
||||
// Generate oneof fields as normal optional fields instead of union.
|
||||
optional bool no_unions = 8 [default = false];
|
||||
|
||||
// integer type tag for a message
|
||||
optional uint32 msgid = 9;
|
||||
|
||||
// decode oneof as anonymous union
|
||||
optional bool anonymous_oneof = 11 [default = false];
|
||||
|
||||
// Proto3 singular field does not generate a "has_" flag
|
||||
optional bool proto3 = 12 [default = false];
|
||||
|
||||
// Force proto3 messages to have no "has_" flag.
|
||||
// This was default behavior until nanopb-0.4.0.
|
||||
optional bool proto3_singular_msgs = 21 [default = false];
|
||||
|
||||
// Generate an enum->string mapping function (can take up lots of space).
|
||||
optional bool enum_to_string = 13 [default = false];
|
||||
|
||||
// Generate bytes arrays with fixed length
|
||||
optional bool fixed_length = 15 [default = false];
|
||||
|
||||
// Generate repeated field with fixed count
|
||||
optional bool fixed_count = 16 [default = false];
|
||||
|
||||
// Generate message-level callback that is called before decoding submessages.
|
||||
// This can be used to set callback fields for submsgs inside oneofs.
|
||||
optional bool submsg_callback = 22 [default = false];
|
||||
|
||||
// Shorten or remove package names from type names.
|
||||
// This option applies only on the file level.
|
||||
optional TypenameMangling mangle_names = 17 [default = M_NONE];
|
||||
|
||||
// Data type for storage associated with callback fields.
|
||||
optional string callback_datatype = 18 [default = "pb_callback_t"];
|
||||
|
||||
// Callback function used for encoding and decoding.
|
||||
// Prior to nanopb-0.4.0, the callback was specified in per-field pb_callback_t
|
||||
// structure. This is still supported, but does not work inside e.g. oneof or pointer
|
||||
// fields. Instead, a new method allows specifying a per-message callback that
|
||||
// will be called for all callback fields in a message type.
|
||||
optional string callback_function = 19 [default = "pb_default_field_callback"];
|
||||
|
||||
// Select the size of field descriptors. This option has to be defined
|
||||
// for the whole message, not per-field. Usually automatic selection is
|
||||
// ok, but if it results in compilation errors you can increase the field
|
||||
// size here.
|
||||
optional DescriptorSize descriptorsize = 20 [default = DS_AUTO];
|
||||
|
||||
// Set default value for has_ fields.
|
||||
optional bool default_has = 23 [default = false];
|
||||
|
||||
// Extra files to include in generated `.pb.h`
|
||||
repeated string include = 24;
|
||||
|
||||
// Automatic includes to exclude from generated `.pb.h`
|
||||
// Same as nanopb_generator.py command line flag -x.
|
||||
repeated string exclude = 26;
|
||||
|
||||
// Package name that applies only for nanopb.
|
||||
optional string package = 25;
|
||||
|
||||
// Override type of the field in generated C code. Only to be used with related field types
|
||||
optional google.protobuf.FieldDescriptorProto.Type type_override = 27;
|
||||
|
||||
// Due to historical reasons, nanopb orders fields in structs by their tag number
|
||||
// instead of the order in .proto. Set this to false to keep the .proto order.
|
||||
// The default value will probably change to false in nanopb-0.5.0.
|
||||
optional bool sort_by_tag = 28 [default = true];
|
||||
|
||||
// Set the FT_DEFAULT field conversion strategy.
|
||||
// A field that can become a static member of a c struct (e.g. int, bool, etc)
|
||||
// will be a a static field.
|
||||
// Fields with dynamic length are converted to either a pointer or a callback.
|
||||
optional FieldType fallback_type = 29 [default = FT_CALLBACK];
|
||||
}
|
||||
|
||||
// Extensions to protoc 'Descriptor' type in order to define options
|
||||
// inside a .proto file.
|
||||
//
|
||||
// Protocol Buffers extension number registry
|
||||
// --------------------------------
|
||||
// Project: Nanopb
|
||||
// Contact: Petteri Aimonen <jpa@kapsi.fi>
|
||||
// Web site: http://kapsi.fi/~jpa/nanopb
|
||||
// Extensions: 1010 (all types)
|
||||
// --------------------------------
|
||||
|
||||
extend google.protobuf.FileOptions {
|
||||
optional NanoPBOptions nanopb_fileopt = 1010;
|
||||
}
|
||||
|
||||
extend google.protobuf.MessageOptions {
|
||||
optional NanoPBOptions nanopb_msgopt = 1010;
|
||||
}
|
||||
|
||||
extend google.protobuf.EnumOptions {
|
||||
optional NanoPBOptions nanopb_enumopt = 1010;
|
||||
}
|
||||
|
||||
extend google.protobuf.FieldOptions {
|
||||
optional NanoPBOptions nanopb = 1010;
|
||||
}
|
||||
|
||||
|
39
third_party/nanopb/generator/protoc
vendored
Executable file
39
third_party/nanopb/generator/protoc
vendored
Executable file
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env python3
|
||||
# This file acts as a drop-in replacement of binary protoc.exe.
|
||||
# It will use either Python-based protoc from grpcio-tools package,
|
||||
# or if it is not available, protoc.exe from path if found.
|
||||
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
from nanopb_generator import invoke_protoc
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Get path of the directory where this script is stored.
|
||||
if getattr(sys, 'frozen', False):
|
||||
mypath = os.path.dirname(sys.executable) # For pyInstaller
|
||||
else:
|
||||
mypath = os.path.dirname(__file__)
|
||||
|
||||
# Avoid recursive calls to self
|
||||
env_paths = os.environ["PATH"].split(os.pathsep)
|
||||
if mypath in env_paths:
|
||||
env_paths.remove(mypath)
|
||||
os.environ["PATH"] = os.pathsep.join(env_paths)
|
||||
|
||||
# Add argument for finding the nanopb generator when using --nanopb_out=
|
||||
# argument to protoc.
|
||||
if os.path.isfile(os.path.join(mypath, "protoc-gen-nanopb.exe")):
|
||||
protoc_gen_nanopb = os.path.join(mypath, "protoc-gen-nanopb.exe")
|
||||
elif os.name == 'nt':
|
||||
protoc_gen_nanopb = os.path.join(mypath, "protoc-gen-nanopb.bat")
|
||||
else:
|
||||
protoc_gen_nanopb = os.path.join(mypath, "protoc-gen-nanopb")
|
||||
|
||||
args = sys.argv[1:]
|
||||
|
||||
if os.path.isfile(protoc_gen_nanopb):
|
||||
args = ['--plugin=protoc-gen-nanopb=%s' % protoc_gen_nanopb] + args
|
||||
|
||||
status = invoke_protoc(['protoc'] + args)
|
||||
sys.exit(status)
|
13
third_party/nanopb/generator/protoc-gen-nanopb
vendored
Executable file
13
third_party/nanopb/generator/protoc-gen-nanopb
vendored
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This file is used to invoke nanopb_generator.py as a plugin
|
||||
# to protoc on Linux and other *nix-style systems.
|
||||
# Use it like this:
|
||||
# protoc --plugin=protoc-gen-nanopb=..../protoc-gen-nanopb --nanopb_out=dir foo.proto
|
||||
#
|
||||
# Note that if you use the binary package of nanopb, the protoc
|
||||
# path is already set up properly and there is no need to give
|
||||
# --plugin= on the command line.
|
||||
|
||||
MYPATH=$(dirname "$0")
|
||||
exec "$MYPATH/nanopb_generator.py" --protoc-plugin
|
16
third_party/nanopb/generator/protoc-gen-nanopb-py2
vendored
Executable file
16
third_party/nanopb/generator/protoc-gen-nanopb-py2
vendored
Executable file
|
@ -0,0 +1,16 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This file is used to invoke nanopb_generator.py2 as a plugin
|
||||
# to protoc on Linux and other *nix-style systems.
|
||||
#
|
||||
# The difference from protoc-gen-nanopb is that this executes with Python 2.
|
||||
#
|
||||
# Use it like this:
|
||||
# protoc --plugin=protoc-gen-nanopb=..../protoc-gen-nanopb-py2 --nanopb_out=dir foo.proto
|
||||
#
|
||||
# Note that if you use the binary package of nanopb, the protoc
|
||||
# path is already set up properly and there is no need to give
|
||||
# --plugin= on the command line.
|
||||
|
||||
MYPATH=$(dirname "$0")
|
||||
exec "$MYPATH/nanopb_generator.py2" --protoc-plugin
|
12
third_party/nanopb/generator/protoc-gen-nanopb.bat
vendored
Normal file
12
third_party/nanopb/generator/protoc-gen-nanopb.bat
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
@echo off
|
||||
:: This file is used to invoke nanopb_generator.py as a plugin
|
||||
:: to protoc on Windows.
|
||||
:: Use it like this:
|
||||
:: protoc --plugin=protoc-gen-nanopb=..../protoc-gen-nanopb.bat --nanopb_out=dir foo.proto
|
||||
::
|
||||
:: Note that if you use the binary package of nanopb, the protoc
|
||||
:: path is already set up properly and there is no need to give
|
||||
:: --plugin= on the command line.
|
||||
|
||||
set mydir=%~dp0
|
||||
python "%mydir%\nanopb_generator.py" --protoc-plugin %*
|
9
third_party/nanopb/generator/protoc.bat
vendored
Normal file
9
third_party/nanopb/generator/protoc.bat
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
@echo off
|
||||
:: This file acts as a drop-in replacement of binary protoc.exe.
|
||||
:: It will use either Python-based protoc from grpcio-tools package,
|
||||
:: or if it is not available, protoc.exe from path if found.
|
||||
|
||||
setLocal enableDelayedExpansion
|
||||
set mydir=%~dp0
|
||||
python "%mydir%\protoc" %*
|
||||
exit /b %ERRORLEVEL%
|
42
third_party/nanopb/library.json
vendored
Normal file
42
third_party/nanopb/library.json
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"name": "Nanopb",
|
||||
"version": "0.4.6.4",
|
||||
"keywords": "protocol buffers, protobuf, google",
|
||||
"description": "Nanopb is a plain-C implementation of Google's Protocol Buffers data format. It is targeted at 32 bit microcontrollers, but is also fit for other embedded systems with tight (<10 kB ROM, <1 kB RAM) memory constraints.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nanopb/nanopb.git"
|
||||
},
|
||||
"authors": [{
|
||||
"name": "Petteri Aimonen",
|
||||
"email": "jpa@nanopb.mail.kapsi.fi",
|
||||
"url": "http://koti.kapsi.fi/jpa/nanopb/"
|
||||
}],
|
||||
"export": {
|
||||
"include": [
|
||||
"*.c",
|
||||
"*.cpp",
|
||||
"*.h",
|
||||
"examples",
|
||||
"generator"
|
||||
],
|
||||
"exclude": [
|
||||
"generator/**/__pycache__",
|
||||
"examples/platformio/.gitignore"
|
||||
]
|
||||
},
|
||||
"build": {
|
||||
"extraScript": "generator/platformio_generator.py",
|
||||
"srcDir": "",
|
||||
"srcFilter": [
|
||||
"+<*.c>"
|
||||
]
|
||||
},
|
||||
"examples": [
|
||||
"examples/platformio/platformio.ini",
|
||||
"examples/platformio/src/*.c",
|
||||
"examples/*/*.c"
|
||||
],
|
||||
"frameworks": "*",
|
||||
"platforms": "*"
|
||||
}
|
911
third_party/nanopb/pb.h
vendored
Normal file
911
third_party/nanopb/pb.h
vendored
Normal file
|
@ -0,0 +1,911 @@
|
|||
/* Common parts of the nanopb library. Most of these are quite low-level
|
||||
* stuff. For the high-level interface, see pb_encode.h and pb_decode.h.
|
||||
*/
|
||||
|
||||
#ifndef PB_H_INCLUDED
|
||||
#define PB_H_INCLUDED
|
||||
|
||||
/*****************************************************************
|
||||
* Nanopb compilation time options. You can change these here by *
|
||||
* uncommenting the lines, or on the compiler command line. *
|
||||
*****************************************************************/
|
||||
|
||||
/* Enable support for dynamically allocated fields */
|
||||
/* #define PB_ENABLE_MALLOC 1 */
|
||||
|
||||
/* Define this if your CPU / compiler combination does not support
|
||||
* unaligned memory access to packed structures. Note that packed
|
||||
* structures are only used when requested in .proto options. */
|
||||
/* #define PB_NO_PACKED_STRUCTS 1 */
|
||||
|
||||
/* Increase the number of required fields that are tracked.
|
||||
* A compiler warning will tell if you need this. */
|
||||
/* #define PB_MAX_REQUIRED_FIELDS 256 */
|
||||
|
||||
/* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */
|
||||
/* #define PB_FIELD_32BIT 1 */
|
||||
|
||||
/* Disable support for error messages in order to save some code space. */
|
||||
/* #define PB_NO_ERRMSG 1 */
|
||||
|
||||
/* Disable support for custom streams (support only memory buffers). */
|
||||
/* #define PB_BUFFER_ONLY 1 */
|
||||
|
||||
/* Disable support for 64-bit datatypes, for compilers without int64_t
|
||||
or to save some code space. */
|
||||
/* #define PB_WITHOUT_64BIT 1 */
|
||||
|
||||
/* Don't encode scalar arrays as packed. This is only to be used when
|
||||
* the decoder on the receiving side cannot process packed scalar arrays.
|
||||
* Such example is older protobuf.js. */
|
||||
/* #define PB_ENCODE_ARRAYS_UNPACKED 1 */
|
||||
|
||||
/* Enable conversion of doubles to floats for platforms that do not
|
||||
* support 64-bit doubles. Most commonly AVR. */
|
||||
/* #define PB_CONVERT_DOUBLE_FLOAT 1 */
|
||||
|
||||
/* Check whether incoming strings are valid UTF-8 sequences. Slows down
|
||||
* the string processing slightly and slightly increases code size. */
|
||||
/* #define PB_VALIDATE_UTF8 1 */
|
||||
|
||||
/* This can be defined if the platform is little-endian and has 8-bit bytes.
|
||||
* Normally it is automatically detected based on __BYTE_ORDER__ macro. */
|
||||
/* #define PB_LITTLE_ENDIAN_8BIT 1 */
|
||||
|
||||
/* Configure static assert mechanism. Instead of changing these, set your
|
||||
* compiler to C11 standard mode if possible. */
|
||||
/* #define PB_C99_STATIC_ASSERT 1 */
|
||||
/* #define PB_NO_STATIC_ASSERT 1 */
|
||||
|
||||
/******************************************************************
|
||||
* You usually don't need to change anything below this line. *
|
||||
* Feel free to look around and use the defined macros, though. *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
/* Version of the nanopb library. Just in case you want to check it in
|
||||
* your own program. */
|
||||
#define NANOPB_VERSION "nanopb-0.4.6"
|
||||
|
||||
/* Include all the system headers needed by nanopb. You will need the
|
||||
* definitions of the following:
|
||||
* - strlen, memcpy, memset functions
|
||||
* - [u]int_least8_t, uint_fast8_t, [u]int_least16_t, [u]int32_t, [u]int64_t
|
||||
* - size_t
|
||||
* - bool
|
||||
*
|
||||
* If you don't have the standard header files, you can instead provide
|
||||
* a custom header that defines or includes all this. In that case,
|
||||
* define PB_SYSTEM_HEADER to the path of this file.
|
||||
*/
|
||||
#ifdef PB_SYSTEM_HEADER
|
||||
#include PB_SYSTEM_HEADER
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Macro for defining packed structures (compiler dependent).
|
||||
* This just reduces memory requirements, but is not required.
|
||||
*/
|
||||
#if defined(PB_NO_PACKED_STRUCTS)
|
||||
/* Disable struct packing */
|
||||
# define PB_PACKED_STRUCT_START
|
||||
# define PB_PACKED_STRUCT_END
|
||||
# define pb_packed
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
/* For GCC and clang */
|
||||
# define PB_PACKED_STRUCT_START
|
||||
# define PB_PACKED_STRUCT_END
|
||||
# define pb_packed __attribute__((packed))
|
||||
#elif defined(__ICCARM__) || defined(__CC_ARM)
|
||||
/* For IAR ARM and Keil MDK-ARM compilers */
|
||||
# define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)")
|
||||
# define PB_PACKED_STRUCT_END _Pragma("pack(pop)")
|
||||
# define pb_packed
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
/* For Microsoft Visual C++ */
|
||||
# define PB_PACKED_STRUCT_START __pragma(pack(push, 1))
|
||||
# define PB_PACKED_STRUCT_END __pragma(pack(pop))
|
||||
# define pb_packed
|
||||
#else
|
||||
/* Unknown compiler */
|
||||
# define PB_PACKED_STRUCT_START
|
||||
# define PB_PACKED_STRUCT_END
|
||||
# define pb_packed
|
||||
#endif
|
||||
|
||||
/* Detect endianness */
|
||||
#ifndef PB_LITTLE_ENDIAN_8BIT
|
||||
#if ((defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
|
||||
defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || \
|
||||
defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || \
|
||||
defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM)) \
|
||||
&& CHAR_BIT == 8
|
||||
#define PB_LITTLE_ENDIAN_8BIT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Handly macro for suppressing unreferenced-parameter compiler warnings. */
|
||||
#ifndef PB_UNUSED
|
||||
#define PB_UNUSED(x) (void)(x)
|
||||
#endif
|
||||
|
||||
/* Harvard-architecture processors may need special attributes for storing
|
||||
* field information in program memory. */
|
||||
#ifndef PB_PROGMEM
|
||||
#ifdef __AVR__
|
||||
#include <avr/pgmspace.h>
|
||||
#define PB_PROGMEM PROGMEM
|
||||
#define PB_PROGMEM_READU32(x) pgm_read_dword(&x)
|
||||
#else
|
||||
#define PB_PROGMEM
|
||||
#define PB_PROGMEM_READU32(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Compile-time assertion, used for checking compatible compilation options.
|
||||
* If this does not work properly on your compiler, use
|
||||
* #define PB_NO_STATIC_ASSERT to disable it.
|
||||
*
|
||||
* But before doing that, check carefully the error message / place where it
|
||||
* comes from to see if the error has a real cause. Unfortunately the error
|
||||
* message is not always very clear to read, but you can see the reason better
|
||||
* in the place where the PB_STATIC_ASSERT macro was called.
|
||||
*/
|
||||
#ifndef PB_NO_STATIC_ASSERT
|
||||
# ifndef PB_STATIC_ASSERT
|
||||
# if defined(__ICCARM__)
|
||||
/* IAR has static_assert keyword but no _Static_assert */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) static_assert(COND,#MSG);
|
||||
# elif defined(PB_C99_STATIC_ASSERT)
|
||||
/* Classic negative-size-array static assert mechanism */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1];
|
||||
# define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER)
|
||||
# define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##_##LINE##_##COUNTER
|
||||
# elif defined(__cplusplus)
|
||||
/* C++11 standard static_assert mechanism */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) static_assert(COND,#MSG);
|
||||
# else
|
||||
/* C11 standard _Static_assert mechanism */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) _Static_assert(COND,#MSG);
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
/* Static asserts disabled by PB_NO_STATIC_ASSERT */
|
||||
# define PB_STATIC_ASSERT(COND,MSG)
|
||||
#endif
|
||||
|
||||
/* Test that PB_STATIC_ASSERT works
|
||||
* If you get errors here, you may need to do one of these:
|
||||
* - Enable C11 standard support in your compiler
|
||||
* - Define PB_C99_STATIC_ASSERT to enable C99 standard support
|
||||
* - Define PB_NO_STATIC_ASSERT to disable static asserts altogether
|
||||
*/
|
||||
PB_STATIC_ASSERT(1, STATIC_ASSERT_IS_NOT_WORKING)
|
||||
|
||||
/* Number of required fields to keep track of. */
|
||||
#ifndef PB_MAX_REQUIRED_FIELDS
|
||||
#define PB_MAX_REQUIRED_FIELDS 64
|
||||
#endif
|
||||
|
||||
#if PB_MAX_REQUIRED_FIELDS < 64
|
||||
#error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64).
|
||||
#endif
|
||||
|
||||
#ifdef PB_WITHOUT_64BIT
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
/* Cannot use doubles without 64-bit types */
|
||||
#undef PB_CONVERT_DOUBLE_FLOAT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* List of possible field types. These are used in the autogenerated code.
|
||||
* Least-significant 4 bits tell the scalar type
|
||||
* Most-significant 4 bits specify repeated/required/packed etc.
|
||||
*/
|
||||
|
||||
typedef uint_least8_t pb_type_t;
|
||||
|
||||
/**** Field data types ****/
|
||||
|
||||
/* Numeric types */
|
||||
#define PB_LTYPE_BOOL 0x00U /* bool */
|
||||
#define PB_LTYPE_VARINT 0x01U /* int32, int64, enum, bool */
|
||||
#define PB_LTYPE_UVARINT 0x02U /* uint32, uint64 */
|
||||
#define PB_LTYPE_SVARINT 0x03U /* sint32, sint64 */
|
||||
#define PB_LTYPE_FIXED32 0x04U /* fixed32, sfixed32, float */
|
||||
#define PB_LTYPE_FIXED64 0x05U /* fixed64, sfixed64, double */
|
||||
|
||||
/* Marker for last packable field type. */
|
||||
#define PB_LTYPE_LAST_PACKABLE 0x05U
|
||||
|
||||
/* Byte array with pre-allocated buffer.
|
||||
* data_size is the length of the allocated PB_BYTES_ARRAY structure. */
|
||||
#define PB_LTYPE_BYTES 0x06U
|
||||
|
||||
/* String with pre-allocated buffer.
|
||||
* data_size is the maximum length. */
|
||||
#define PB_LTYPE_STRING 0x07U
|
||||
|
||||
/* Submessage
|
||||
* submsg_fields is pointer to field descriptions */
|
||||
#define PB_LTYPE_SUBMESSAGE 0x08U
|
||||
|
||||
/* Submessage with pre-decoding callback
|
||||
* The pre-decoding callback is stored as pb_callback_t right before pSize.
|
||||
* submsg_fields is pointer to field descriptions */
|
||||
#define PB_LTYPE_SUBMSG_W_CB 0x09U
|
||||
|
||||
/* Extension pseudo-field
|
||||
* The field contains a pointer to pb_extension_t */
|
||||
#define PB_LTYPE_EXTENSION 0x0AU
|
||||
|
||||
/* Byte array with inline, pre-allocated byffer.
|
||||
* data_size is the length of the inline, allocated buffer.
|
||||
* This differs from PB_LTYPE_BYTES by defining the element as
|
||||
* pb_byte_t[data_size] rather than pb_bytes_array_t. */
|
||||
#define PB_LTYPE_FIXED_LENGTH_BYTES 0x0BU
|
||||
|
||||
/* Number of declared LTYPES */
|
||||
#define PB_LTYPES_COUNT 0x0CU
|
||||
#define PB_LTYPE_MASK 0x0FU
|
||||
|
||||
/**** Field repetition rules ****/
|
||||
|
||||
#define PB_HTYPE_REQUIRED 0x00U
|
||||
#define PB_HTYPE_OPTIONAL 0x10U
|
||||
#define PB_HTYPE_SINGULAR 0x10U
|
||||
#define PB_HTYPE_REPEATED 0x20U
|
||||
#define PB_HTYPE_FIXARRAY 0x20U
|
||||
#define PB_HTYPE_ONEOF 0x30U
|
||||
#define PB_HTYPE_MASK 0x30U
|
||||
|
||||
/**** Field allocation types ****/
|
||||
|
||||
#define PB_ATYPE_STATIC 0x00U
|
||||
#define PB_ATYPE_POINTER 0x80U
|
||||
#define PB_ATYPE_CALLBACK 0x40U
|
||||
#define PB_ATYPE_MASK 0xC0U
|
||||
|
||||
#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK)
|
||||
#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK)
|
||||
#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK)
|
||||
#define PB_LTYPE_IS_SUBMSG(x) (PB_LTYPE(x) == PB_LTYPE_SUBMESSAGE || \
|
||||
PB_LTYPE(x) == PB_LTYPE_SUBMSG_W_CB)
|
||||
|
||||
/* Data type used for storing sizes of struct fields
|
||||
* and array counts.
|
||||
*/
|
||||
#if defined(PB_FIELD_32BIT)
|
||||
typedef uint32_t pb_size_t;
|
||||
typedef int32_t pb_ssize_t;
|
||||
#else
|
||||
typedef uint_least16_t pb_size_t;
|
||||
typedef int_least16_t pb_ssize_t;
|
||||
#endif
|
||||
#define PB_SIZE_MAX ((pb_size_t)-1)
|
||||
|
||||
/* Data type for storing encoded data and other byte streams.
|
||||
* This typedef exists to support platforms where uint8_t does not exist.
|
||||
* You can regard it as equivalent on uint8_t on other platforms.
|
||||
*/
|
||||
typedef uint_least8_t pb_byte_t;
|
||||
|
||||
/* Forward declaration of struct types */
|
||||
typedef struct pb_istream_s pb_istream_t;
|
||||
typedef struct pb_ostream_s pb_ostream_t;
|
||||
typedef struct pb_field_iter_s pb_field_iter_t;
|
||||
|
||||
/* This structure is used in auto-generated constants
|
||||
* to specify struct fields.
|
||||
*/
|
||||
typedef struct pb_msgdesc_s pb_msgdesc_t;
|
||||
struct pb_msgdesc_s {
|
||||
const uint32_t *field_info;
|
||||
const pb_msgdesc_t * const * submsg_info;
|
||||
const pb_byte_t *default_value;
|
||||
|
||||
bool (*field_callback)(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field);
|
||||
|
||||
pb_size_t field_count;
|
||||
pb_size_t required_field_count;
|
||||
pb_size_t largest_tag;
|
||||
};
|
||||
|
||||
/* Iterator for message descriptor */
|
||||
struct pb_field_iter_s {
|
||||
const pb_msgdesc_t *descriptor; /* Pointer to message descriptor constant */
|
||||
void *message; /* Pointer to start of the structure */
|
||||
|
||||
pb_size_t index; /* Index of the field */
|
||||
pb_size_t field_info_index; /* Index to descriptor->field_info array */
|
||||
pb_size_t required_field_index; /* Index that counts only the required fields */
|
||||
pb_size_t submessage_index; /* Index that counts only submessages */
|
||||
|
||||
pb_size_t tag; /* Tag of current field */
|
||||
pb_size_t data_size; /* sizeof() of a single item */
|
||||
pb_size_t array_size; /* Number of array entries */
|
||||
pb_type_t type; /* Type of current field */
|
||||
|
||||
void *pField; /* Pointer to current field in struct */
|
||||
void *pData; /* Pointer to current data contents. Different than pField for arrays and pointers. */
|
||||
void *pSize; /* Pointer to count/has field */
|
||||
|
||||
const pb_msgdesc_t *submsg_desc; /* For submessage fields, pointer to field descriptor for the submessage. */
|
||||
};
|
||||
|
||||
/* For compatibility with legacy code */
|
||||
typedef pb_field_iter_t pb_field_t;
|
||||
|
||||
/* Make sure that the standard integer types are of the expected sizes.
|
||||
* Otherwise fixed32/fixed64 fields can break.
|
||||
*
|
||||
* If you get errors here, it probably means that your stdint.h is not
|
||||
* correct for your platform.
|
||||
*/
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
PB_STATIC_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t), INT64_T_WRONG_SIZE)
|
||||
PB_STATIC_ASSERT(sizeof(uint64_t) == 2 * sizeof(uint32_t), UINT64_T_WRONG_SIZE)
|
||||
#endif
|
||||
|
||||
/* This structure is used for 'bytes' arrays.
|
||||
* It has the number of bytes in the beginning, and after that an array.
|
||||
* Note that actual structs used will have a different length of bytes array.
|
||||
*/
|
||||
#define PB_BYTES_ARRAY_T(n) struct { pb_size_t size; pb_byte_t bytes[n]; }
|
||||
#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) ((size_t)n + offsetof(pb_bytes_array_t, bytes))
|
||||
|
||||
struct pb_bytes_array_s {
|
||||
pb_size_t size;
|
||||
pb_byte_t bytes[1];
|
||||
};
|
||||
typedef struct pb_bytes_array_s pb_bytes_array_t;
|
||||
|
||||
/* This structure is used for giving the callback function.
|
||||
* It is stored in the message structure and filled in by the method that
|
||||
* calls pb_decode.
|
||||
*
|
||||
* The decoding callback will be given a limited-length stream
|
||||
* If the wire type was string, the length is the length of the string.
|
||||
* If the wire type was a varint/fixed32/fixed64, the length is the length
|
||||
* of the actual value.
|
||||
* The function may be called multiple times (especially for repeated types,
|
||||
* but also otherwise if the message happens to contain the field multiple
|
||||
* times.)
|
||||
*
|
||||
* The encoding callback will receive the actual output stream.
|
||||
* It should write all the data in one call, including the field tag and
|
||||
* wire type. It can write multiple fields.
|
||||
*
|
||||
* The callback can be null if you want to skip a field.
|
||||
*/
|
||||
typedef struct pb_callback_s pb_callback_t;
|
||||
struct pb_callback_s {
|
||||
/* Callback functions receive a pointer to the arg field.
|
||||
* You can access the value of the field as *arg, and modify it if needed.
|
||||
*/
|
||||
union {
|
||||
bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg);
|
||||
bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg);
|
||||
} funcs;
|
||||
|
||||
/* Free arg for use by callback */
|
||||
void *arg;
|
||||
};
|
||||
|
||||
extern bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field);
|
||||
|
||||
/* Wire types. Library user needs these only in encoder callbacks. */
|
||||
typedef enum {
|
||||
PB_WT_VARINT = 0,
|
||||
PB_WT_64BIT = 1,
|
||||
PB_WT_STRING = 2,
|
||||
PB_WT_32BIT = 5,
|
||||
PB_WT_PACKED = 255 /* PB_WT_PACKED is internal marker for packed arrays. */
|
||||
} pb_wire_type_t;
|
||||
|
||||
/* Structure for defining the handling of unknown/extension fields.
|
||||
* Usually the pb_extension_type_t structure is automatically generated,
|
||||
* while the pb_extension_t structure is created by the user. However,
|
||||
* if you want to catch all unknown fields, you can also create a custom
|
||||
* pb_extension_type_t with your own callback.
|
||||
*/
|
||||
typedef struct pb_extension_type_s pb_extension_type_t;
|
||||
typedef struct pb_extension_s pb_extension_t;
|
||||
struct pb_extension_type_s {
|
||||
/* Called for each unknown field in the message.
|
||||
* If you handle the field, read off all of its data and return true.
|
||||
* If you do not handle the field, do not read anything and return true.
|
||||
* If you run into an error, return false.
|
||||
* Set to NULL for default handler.
|
||||
*/
|
||||
bool (*decode)(pb_istream_t *stream, pb_extension_t *extension,
|
||||
uint32_t tag, pb_wire_type_t wire_type);
|
||||
|
||||
/* Called once after all regular fields have been encoded.
|
||||
* If you have something to write, do so and return true.
|
||||
* If you do not have anything to write, just return true.
|
||||
* If you run into an error, return false.
|
||||
* Set to NULL for default handler.
|
||||
*/
|
||||
bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension);
|
||||
|
||||
/* Free field for use by the callback. */
|
||||
const void *arg;
|
||||
};
|
||||
|
||||
struct pb_extension_s {
|
||||
/* Type describing the extension field. Usually you'll initialize
|
||||
* this to a pointer to the automatically generated structure. */
|
||||
const pb_extension_type_t *type;
|
||||
|
||||
/* Destination for the decoded data. This must match the datatype
|
||||
* of the extension field. */
|
||||
void *dest;
|
||||
|
||||
/* Pointer to the next extension handler, or NULL.
|
||||
* If this extension does not match a field, the next handler is
|
||||
* automatically called. */
|
||||
pb_extension_t *next;
|
||||
|
||||
/* The decoder sets this to true if the extension was found.
|
||||
* Ignored for encoding. */
|
||||
bool found;
|
||||
};
|
||||
|
||||
#define pb_extension_init_zero {NULL,NULL,NULL,false}
|
||||
|
||||
/* Memory allocation functions to use. You can define pb_realloc and
|
||||
* pb_free to custom functions if you want. */
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
# ifndef pb_realloc
|
||||
# define pb_realloc(ptr, size) realloc(ptr, size)
|
||||
# endif
|
||||
# ifndef pb_free
|
||||
# define pb_free(ptr) free(ptr)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* This is used to inform about need to regenerate .pb.h/.pb.c files. */
|
||||
#define PB_PROTO_HEADER_VERSION 40
|
||||
|
||||
/* These macros are used to declare pb_field_t's in the constant array. */
|
||||
/* Size of a structure member, in bytes. */
|
||||
#define pb_membersize(st, m) (sizeof ((st*)0)->m)
|
||||
/* Number of entries in an array. */
|
||||
#define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0]))
|
||||
/* Delta from start of one member to the start of another member. */
|
||||
#define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2))
|
||||
|
||||
/* Force expansion of macro value */
|
||||
#define PB_EXPAND(x) x
|
||||
|
||||
/* Binding of a message field set into a specific structure */
|
||||
#define PB_BIND(msgname, structname, width) \
|
||||
const uint32_t structname ## _field_info[] PB_PROGMEM = \
|
||||
{ \
|
||||
msgname ## _FIELDLIST(PB_GEN_FIELD_INFO_ ## width, structname) \
|
||||
0 \
|
||||
}; \
|
||||
const pb_msgdesc_t* const structname ## _submsg_info[] = \
|
||||
{ \
|
||||
msgname ## _FIELDLIST(PB_GEN_SUBMSG_INFO, structname) \
|
||||
NULL \
|
||||
}; \
|
||||
const pb_msgdesc_t structname ## _msg = \
|
||||
{ \
|
||||
structname ## _field_info, \
|
||||
structname ## _submsg_info, \
|
||||
msgname ## _DEFAULT, \
|
||||
msgname ## _CALLBACK, \
|
||||
0 msgname ## _FIELDLIST(PB_GEN_FIELD_COUNT, structname), \
|
||||
0 msgname ## _FIELDLIST(PB_GEN_REQ_FIELD_COUNT, structname), \
|
||||
0 msgname ## _FIELDLIST(PB_GEN_LARGEST_TAG, structname), \
|
||||
}; \
|
||||
msgname ## _FIELDLIST(PB_GEN_FIELD_INFO_ASSERT_ ## width, structname)
|
||||
|
||||
#define PB_GEN_FIELD_COUNT(structname, atype, htype, ltype, fieldname, tag) +1
|
||||
#define PB_GEN_REQ_FIELD_COUNT(structname, atype, htype, ltype, fieldname, tag) \
|
||||
+ (PB_HTYPE_ ## htype == PB_HTYPE_REQUIRED)
|
||||
#define PB_GEN_LARGEST_TAG(structname, atype, htype, ltype, fieldname, tag) \
|
||||
* 0 + tag
|
||||
|
||||
/* X-macro for generating the entries in struct_field_info[] array. */
|
||||
#define PB_GEN_FIELD_INFO_1(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_1(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_2(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_2(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_4(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_4(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_8(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_8(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_AUTO(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_AUTO2(PB_FIELDINFO_WIDTH_AUTO(_PB_ATYPE_ ## atype, _PB_HTYPE_ ## htype, _PB_LTYPE_ ## ltype), \
|
||||
tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_FIELDINFO_AUTO2(width, tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_FIELDINFO_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size)
|
||||
|
||||
#define PB_FIELDINFO_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_FIELDINFO_ ## width(tag, type, data_offset, data_size, size_offset, array_size)
|
||||
|
||||
/* X-macro for generating asserts that entries fit in struct_field_info[] array.
|
||||
* The structure of macros here must match the structure above in PB_GEN_FIELD_INFO_x(),
|
||||
* but it is not easily reused because of how macro substitutions work. */
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_1(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_ASSERT_1(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_2(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_ASSERT_2(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_4(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_ASSERT_4(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_8(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_ASSERT_8(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_AUTO(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_ASSERT_AUTO2(PB_FIELDINFO_WIDTH_AUTO(_PB_ATYPE_ ## atype, _PB_HTYPE_ ## htype, _PB_LTYPE_ ## ltype), \
|
||||
tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_FIELDINFO_ASSERT_AUTO2(width, tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_FIELDINFO_ASSERT_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size)
|
||||
|
||||
#define PB_FIELDINFO_ASSERT_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_FIELDINFO_ASSERT_ ## width(tag, type, data_offset, data_size, size_offset, array_size)
|
||||
|
||||
#define PB_DATA_OFFSET_STATIC(htype, structname, fieldname) PB_DO ## htype(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_POINTER(htype, structname, fieldname) PB_DO ## htype(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_CALLBACK(htype, structname, fieldname) PB_DO ## htype(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_REQUIRED(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_SINGULAR(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_ONEOF(structname, fieldname) offsetof(structname, PB_ONEOF_NAME(FULL, fieldname))
|
||||
#define PB_DO_PB_HTYPE_OPTIONAL(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_REPEATED(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_FIXARRAY(structname, fieldname) offsetof(structname, fieldname)
|
||||
|
||||
#define PB_SIZE_OFFSET_STATIC(htype, structname, fieldname) PB_SO ## htype(structname, fieldname)
|
||||
#define PB_SIZE_OFFSET_POINTER(htype, structname, fieldname) PB_SO_PTR ## htype(structname, fieldname)
|
||||
#define PB_SIZE_OFFSET_CALLBACK(htype, structname, fieldname) PB_SO_CB ## htype(structname, fieldname)
|
||||
#define PB_SO_PB_HTYPE_REQUIRED(structname, fieldname) 0
|
||||
#define PB_SO_PB_HTYPE_SINGULAR(structname, fieldname) 0
|
||||
#define PB_SO_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF2(structname, PB_ONEOF_NAME(FULL, fieldname), PB_ONEOF_NAME(UNION, fieldname))
|
||||
#define PB_SO_PB_HTYPE_ONEOF2(structname, fullname, unionname) PB_SO_PB_HTYPE_ONEOF3(structname, fullname, unionname)
|
||||
#define PB_SO_PB_HTYPE_ONEOF3(structname, fullname, unionname) pb_delta(structname, fullname, which_ ## unionname)
|
||||
#define PB_SO_PB_HTYPE_OPTIONAL(structname, fieldname) pb_delta(structname, fieldname, has_ ## fieldname)
|
||||
#define PB_SO_PB_HTYPE_REPEATED(structname, fieldname) pb_delta(structname, fieldname, fieldname ## _count)
|
||||
#define PB_SO_PB_HTYPE_FIXARRAY(structname, fieldname) 0
|
||||
#define PB_SO_PTR_PB_HTYPE_REQUIRED(structname, fieldname) 0
|
||||
#define PB_SO_PTR_PB_HTYPE_SINGULAR(structname, fieldname) 0
|
||||
#define PB_SO_PTR_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF(structname, fieldname)
|
||||
#define PB_SO_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) 0
|
||||
#define PB_SO_PTR_PB_HTYPE_REPEATED(structname, fieldname) PB_SO_PB_HTYPE_REPEATED(structname, fieldname)
|
||||
#define PB_SO_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_REQUIRED(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_SINGULAR(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF(structname, fieldname)
|
||||
#define PB_SO_CB_PB_HTYPE_OPTIONAL(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_REPEATED(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_FIXARRAY(structname, fieldname) 0
|
||||
|
||||
#define PB_ARRAY_SIZE_STATIC(htype, structname, fieldname) PB_AS ## htype(structname, fieldname)
|
||||
#define PB_ARRAY_SIZE_POINTER(htype, structname, fieldname) PB_AS_PTR ## htype(structname, fieldname)
|
||||
#define PB_ARRAY_SIZE_CALLBACK(htype, structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_REQUIRED(structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_SINGULAR(structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_OPTIONAL(structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_ONEOF(structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_REPEATED(structname, fieldname) pb_arraysize(structname, fieldname)
|
||||
#define PB_AS_PB_HTYPE_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname)
|
||||
#define PB_AS_PTR_PB_HTYPE_REQUIRED(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_SINGULAR(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_ONEOF(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_REPEATED(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname[0])
|
||||
|
||||
#define PB_DATA_SIZE_STATIC(htype, structname, fieldname) PB_DS ## htype(structname, fieldname)
|
||||
#define PB_DATA_SIZE_POINTER(htype, structname, fieldname) PB_DS_PTR ## htype(structname, fieldname)
|
||||
#define PB_DATA_SIZE_CALLBACK(htype, structname, fieldname) PB_DS_CB ## htype(structname, fieldname)
|
||||
#define PB_DS_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname))
|
||||
#define PB_DS_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0][0])
|
||||
#define PB_DS_CB_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_CB_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_CB_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_CB_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname))
|
||||
#define PB_DS_CB_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_CB_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
|
||||
#define PB_ONEOF_NAME(type, tuple) PB_EXPAND(PB_ONEOF_NAME_ ## type tuple)
|
||||
#define PB_ONEOF_NAME_UNION(unionname,membername,fullname) unionname
|
||||
#define PB_ONEOF_NAME_MEMBER(unionname,membername,fullname) membername
|
||||
#define PB_ONEOF_NAME_FULL(unionname,membername,fullname) fullname
|
||||
|
||||
#define PB_GEN_SUBMSG_INFO(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_SUBMSG_INFO_ ## htype(_PB_LTYPE_ ## ltype, structname, fieldname)
|
||||
|
||||
#define PB_SUBMSG_INFO_REQUIRED(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_SINGULAR(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_OPTIONAL(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_ONEOF(ltype, structname, fieldname) PB_SUBMSG_INFO_ONEOF2(ltype, structname, PB_ONEOF_NAME(UNION, fieldname), PB_ONEOF_NAME(MEMBER, fieldname))
|
||||
#define PB_SUBMSG_INFO_ONEOF2(ltype, structname, unionname, membername) PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername)
|
||||
#define PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername) PB_SI ## ltype(structname ## _ ## unionname ## _ ## membername ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_REPEATED(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_FIXARRAY(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SI_PB_LTYPE_BOOL(t)
|
||||
#define PB_SI_PB_LTYPE_BYTES(t)
|
||||
#define PB_SI_PB_LTYPE_DOUBLE(t)
|
||||
#define PB_SI_PB_LTYPE_ENUM(t)
|
||||
#define PB_SI_PB_LTYPE_UENUM(t)
|
||||
#define PB_SI_PB_LTYPE_FIXED32(t)
|
||||
#define PB_SI_PB_LTYPE_FIXED64(t)
|
||||
#define PB_SI_PB_LTYPE_FLOAT(t)
|
||||
#define PB_SI_PB_LTYPE_INT32(t)
|
||||
#define PB_SI_PB_LTYPE_INT64(t)
|
||||
#define PB_SI_PB_LTYPE_MESSAGE(t) PB_SUBMSG_DESCRIPTOR(t)
|
||||
#define PB_SI_PB_LTYPE_MSG_W_CB(t) PB_SUBMSG_DESCRIPTOR(t)
|
||||
#define PB_SI_PB_LTYPE_SFIXED32(t)
|
||||
#define PB_SI_PB_LTYPE_SFIXED64(t)
|
||||
#define PB_SI_PB_LTYPE_SINT32(t)
|
||||
#define PB_SI_PB_LTYPE_SINT64(t)
|
||||
#define PB_SI_PB_LTYPE_STRING(t)
|
||||
#define PB_SI_PB_LTYPE_UINT32(t)
|
||||
#define PB_SI_PB_LTYPE_UINT64(t)
|
||||
#define PB_SI_PB_LTYPE_EXTENSION(t)
|
||||
#define PB_SI_PB_LTYPE_FIXED_LENGTH_BYTES(t)
|
||||
#define PB_SUBMSG_DESCRIPTOR(t) &(t ## _msg),
|
||||
|
||||
/* The field descriptors use a variable width format, with width of either
|
||||
* 1, 2, 4 or 8 of 32-bit words. The two lowest bytes of the first byte always
|
||||
* encode the descriptor size, 6 lowest bits of field tag number, and 8 bits
|
||||
* of the field type.
|
||||
*
|
||||
* Descriptor size is encoded as 0 = 1 word, 1 = 2 words, 2 = 4 words, 3 = 8 words.
|
||||
*
|
||||
* Formats, listed starting with the least significant bit of the first word.
|
||||
* 1 word: [2-bit len] [6-bit tag] [8-bit type] [8-bit data_offset] [4-bit size_offset] [4-bit data_size]
|
||||
*
|
||||
* 2 words: [2-bit len] [6-bit tag] [8-bit type] [12-bit array_size] [4-bit size_offset]
|
||||
* [16-bit data_offset] [12-bit data_size] [4-bit tag>>6]
|
||||
*
|
||||
* 4 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit array_size]
|
||||
* [8-bit size_offset] [24-bit tag>>6]
|
||||
* [32-bit data_offset]
|
||||
* [32-bit data_size]
|
||||
*
|
||||
* 8 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit reserved]
|
||||
* [8-bit size_offset] [24-bit tag>>6]
|
||||
* [32-bit data_offset]
|
||||
* [32-bit data_size]
|
||||
* [32-bit array_size]
|
||||
* [32-bit reserved]
|
||||
* [32-bit reserved]
|
||||
* [32-bit reserved]
|
||||
*/
|
||||
|
||||
#define PB_FIELDINFO_1(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
(0 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(data_offset) & 0xFF) << 16) | \
|
||||
(((uint32_t)(size_offset) & 0x0F) << 24) | (((uint32_t)(data_size) & 0x0F) << 28)),
|
||||
|
||||
#define PB_FIELDINFO_2(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
(1 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(array_size) & 0xFFF) << 16) | (((uint32_t)(size_offset) & 0x0F) << 28)), \
|
||||
(((uint32_t)(data_offset) & 0xFFFF) | (((uint32_t)(data_size) & 0xFFF) << 16) | (((uint32_t)(tag) & 0x3c0) << 22)),
|
||||
|
||||
#define PB_FIELDINFO_4(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
(2 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(array_size) & 0xFFFF) << 16)), \
|
||||
((uint32_t)(int_least8_t)(size_offset) | (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \
|
||||
(data_offset), (data_size),
|
||||
|
||||
#define PB_FIELDINFO_8(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
(3 | (((tag) << 2) & 0xFF) | ((type) << 8)), \
|
||||
((uint32_t)(int_least8_t)(size_offset) | (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \
|
||||
(data_offset), (data_size), (array_size), 0, 0, 0,
|
||||
|
||||
/* These assertions verify that the field information fits in the allocated space.
|
||||
* The generator tries to automatically determine the correct width that can fit all
|
||||
* data associated with a message. These asserts will fail only if there has been a
|
||||
* problem in the automatic logic - this may be worth reporting as a bug. As a workaround,
|
||||
* you can increase the descriptor width by defining PB_FIELDINFO_WIDTH or by setting
|
||||
* descriptorsize option in .options file.
|
||||
*/
|
||||
#define PB_FITS(value,bits) ((uint32_t)(value) < ((uint32_t)1<<bits))
|
||||
#define PB_FIELDINFO_ASSERT_1(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_STATIC_ASSERT(PB_FITS(tag,6) && PB_FITS(data_offset,8) && PB_FITS(size_offset,4) && PB_FITS(data_size,4) && PB_FITS(array_size,1), FIELDINFO_DOES_NOT_FIT_width1_field ## tag)
|
||||
|
||||
#define PB_FIELDINFO_ASSERT_2(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_STATIC_ASSERT(PB_FITS(tag,10) && PB_FITS(data_offset,16) && PB_FITS(size_offset,4) && PB_FITS(data_size,12) && PB_FITS(array_size,12), FIELDINFO_DOES_NOT_FIT_width2_field ## tag)
|
||||
|
||||
#ifndef PB_FIELD_32BIT
|
||||
/* Maximum field sizes are still 16-bit if pb_size_t is 16-bit */
|
||||
#define PB_FIELDINFO_ASSERT_4(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_STATIC_ASSERT(PB_FITS(tag,16) && PB_FITS(data_offset,16) && PB_FITS((int_least8_t)size_offset,8) && PB_FITS(data_size,16) && PB_FITS(array_size,16), FIELDINFO_DOES_NOT_FIT_width4_field ## tag)
|
||||
|
||||
#define PB_FIELDINFO_ASSERT_8(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_STATIC_ASSERT(PB_FITS(tag,16) && PB_FITS(data_offset,16) && PB_FITS((int_least8_t)size_offset,8) && PB_FITS(data_size,16) && PB_FITS(array_size,16), FIELDINFO_DOES_NOT_FIT_width8_field ## tag)
|
||||
#else
|
||||
/* Up to 32-bit fields supported.
|
||||
* Note that the checks are against 31 bits to avoid compiler warnings about shift wider than type in the test.
|
||||
* I expect that there is no reasonable use for >2GB messages with nanopb anyway.
|
||||
*/
|
||||
#define PB_FIELDINFO_ASSERT_4(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_STATIC_ASSERT(PB_FITS(tag,30) && PB_FITS(data_offset,31) && PB_FITS(size_offset,8) && PB_FITS(data_size,31) && PB_FITS(array_size,16), FIELDINFO_DOES_NOT_FIT_width4_field ## tag)
|
||||
|
||||
#define PB_FIELDINFO_ASSERT_8(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_STATIC_ASSERT(PB_FITS(tag,30) && PB_FITS(data_offset,31) && PB_FITS(size_offset,8) && PB_FITS(data_size,31) && PB_FITS(array_size,31), FIELDINFO_DOES_NOT_FIT_width8_field ## tag)
|
||||
#endif
|
||||
|
||||
|
||||
/* Automatic picking of FIELDINFO width:
|
||||
* Uses width 1 when possible, otherwise resorts to width 2.
|
||||
* This is used when PB_BIND() is called with "AUTO" as the argument.
|
||||
* The generator will give explicit size argument when it knows that a message
|
||||
* structure grows beyond 1-word format limits.
|
||||
*/
|
||||
#define PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype) PB_FI_WIDTH ## atype(htype, ltype)
|
||||
#define PB_FI_WIDTH_PB_ATYPE_STATIC(htype, ltype) PB_FI_WIDTH ## htype(ltype)
|
||||
#define PB_FI_WIDTH_PB_ATYPE_POINTER(htype, ltype) PB_FI_WIDTH ## htype(ltype)
|
||||
#define PB_FI_WIDTH_PB_ATYPE_CALLBACK(htype, ltype) 2
|
||||
#define PB_FI_WIDTH_PB_HTYPE_REQUIRED(ltype) PB_FI_WIDTH ## ltype
|
||||
#define PB_FI_WIDTH_PB_HTYPE_SINGULAR(ltype) PB_FI_WIDTH ## ltype
|
||||
#define PB_FI_WIDTH_PB_HTYPE_OPTIONAL(ltype) PB_FI_WIDTH ## ltype
|
||||
#define PB_FI_WIDTH_PB_HTYPE_ONEOF(ltype) PB_FI_WIDTH ## ltype
|
||||
#define PB_FI_WIDTH_PB_HTYPE_REPEATED(ltype) 2
|
||||
#define PB_FI_WIDTH_PB_HTYPE_FIXARRAY(ltype) 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_BOOL 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_BYTES 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_DOUBLE 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_ENUM 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_UENUM 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_FIXED32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_FIXED64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_FLOAT 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_INT32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_INT64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_MESSAGE 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_MSG_W_CB 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_SFIXED32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_SFIXED64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_SINT32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_SINT64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_STRING 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_UINT32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_UINT64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_EXTENSION 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_FIXED_LENGTH_BYTES 2
|
||||
|
||||
/* The mapping from protobuf types to LTYPEs is done using these macros. */
|
||||
#define PB_LTYPE_MAP_BOOL PB_LTYPE_BOOL
|
||||
#define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES
|
||||
#define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64
|
||||
#define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT
|
||||
#define PB_LTYPE_MAP_UENUM PB_LTYPE_UVARINT
|
||||
#define PB_LTYPE_MAP_FIXED32 PB_LTYPE_FIXED32
|
||||
#define PB_LTYPE_MAP_FIXED64 PB_LTYPE_FIXED64
|
||||
#define PB_LTYPE_MAP_FLOAT PB_LTYPE_FIXED32
|
||||
#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT
|
||||
#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT
|
||||
#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE
|
||||
#define PB_LTYPE_MAP_MSG_W_CB PB_LTYPE_SUBMSG_W_CB
|
||||
#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32
|
||||
#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64
|
||||
#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT
|
||||
#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT
|
||||
#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING
|
||||
#define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT
|
||||
#define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT
|
||||
#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION
|
||||
#define PB_LTYPE_MAP_FIXED_LENGTH_BYTES PB_LTYPE_FIXED_LENGTH_BYTES
|
||||
|
||||
/* These macros are used for giving out error messages.
|
||||
* They are mostly a debugging aid; the main error information
|
||||
* is the true/false return value from functions.
|
||||
* Some code space can be saved by disabling the error
|
||||
* messages if not used.
|
||||
*
|
||||
* PB_SET_ERROR() sets the error message if none has been set yet.
|
||||
* msg must be a constant string literal.
|
||||
* PB_GET_ERROR() always returns a pointer to a string.
|
||||
* PB_RETURN_ERROR() sets the error and returns false from current
|
||||
* function.
|
||||
*/
|
||||
#ifdef PB_NO_ERRMSG
|
||||
#define PB_SET_ERROR(stream, msg) PB_UNUSED(stream)
|
||||
#define PB_GET_ERROR(stream) "(errmsg disabled)"
|
||||
#else
|
||||
#define PB_SET_ERROR(stream, msg) (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg))
|
||||
#define PB_GET_ERROR(stream) ((stream)->errmsg ? (stream)->errmsg : "(none)")
|
||||
#endif
|
||||
|
||||
#define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus >= 201103L
|
||||
#define PB_CONSTEXPR constexpr
|
||||
#else // __cplusplus >= 201103L
|
||||
#define PB_CONSTEXPR
|
||||
#endif // __cplusplus >= 201103L
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#define PB_INLINE_CONSTEXPR inline constexpr
|
||||
#else // __cplusplus >= 201703L
|
||||
#define PB_INLINE_CONSTEXPR PB_CONSTEXPR
|
||||
#endif // __cplusplus >= 201703L
|
||||
|
||||
namespace nanopb {
|
||||
// Each type will be partially specialized by the generator.
|
||||
template <typename GenMessageT> struct MessageDescriptor;
|
||||
} // namespace nanopb
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
388
third_party/nanopb/pb_common.c
vendored
Normal file
388
third_party/nanopb/pb_common.c
vendored
Normal file
|
@ -0,0 +1,388 @@
|
|||
/* pb_common.c: Common support functions for pb_encode.c and pb_decode.c.
|
||||
*
|
||||
* 2014 Petteri Aimonen <jpa@kapsi.fi>
|
||||
*/
|
||||
|
||||
#include "pb_common.h"
|
||||
|
||||
static bool load_descriptor_values(pb_field_iter_t *iter)
|
||||
{
|
||||
uint32_t word0;
|
||||
uint32_t data_offset;
|
||||
int_least8_t size_offset;
|
||||
|
||||
if (iter->index >= iter->descriptor->field_count)
|
||||
return false;
|
||||
|
||||
word0 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
|
||||
iter->type = (pb_type_t)((word0 >> 8) & 0xFF);
|
||||
|
||||
switch(word0 & 3)
|
||||
{
|
||||
case 0: {
|
||||
/* 1-word format */
|
||||
iter->array_size = 1;
|
||||
iter->tag = (pb_size_t)((word0 >> 2) & 0x3F);
|
||||
size_offset = (int_least8_t)((word0 >> 24) & 0x0F);
|
||||
data_offset = (word0 >> 16) & 0xFF;
|
||||
iter->data_size = (pb_size_t)((word0 >> 28) & 0x0F);
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
/* 2-word format */
|
||||
uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
|
||||
|
||||
iter->array_size = (pb_size_t)((word0 >> 16) & 0x0FFF);
|
||||
iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 28) << 6));
|
||||
size_offset = (int_least8_t)((word0 >> 28) & 0x0F);
|
||||
data_offset = word1 & 0xFFFF;
|
||||
iter->data_size = (pb_size_t)((word1 >> 16) & 0x0FFF);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
/* 4-word format */
|
||||
uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
|
||||
uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]);
|
||||
uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]);
|
||||
|
||||
iter->array_size = (pb_size_t)(word0 >> 16);
|
||||
iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6));
|
||||
size_offset = (int_least8_t)(word1 & 0xFF);
|
||||
data_offset = word2;
|
||||
iter->data_size = (pb_size_t)word3;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
/* 8-word format */
|
||||
uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
|
||||
uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]);
|
||||
uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]);
|
||||
uint32_t word4 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 4]);
|
||||
|
||||
iter->array_size = (pb_size_t)word4;
|
||||
iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6));
|
||||
size_offset = (int_least8_t)(word1 & 0xFF);
|
||||
data_offset = word2;
|
||||
iter->data_size = (pb_size_t)word3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!iter->message)
|
||||
{
|
||||
/* Avoid doing arithmetic on null pointers, it is undefined */
|
||||
iter->pField = NULL;
|
||||
iter->pSize = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->pField = (char*)iter->message + data_offset;
|
||||
|
||||
if (size_offset)
|
||||
{
|
||||
iter->pSize = (char*)iter->pField - size_offset;
|
||||
}
|
||||
else if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED &&
|
||||
(PB_ATYPE(iter->type) == PB_ATYPE_STATIC ||
|
||||
PB_ATYPE(iter->type) == PB_ATYPE_POINTER))
|
||||
{
|
||||
/* Fixed count array */
|
||||
iter->pSize = &iter->array_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->pSize = NULL;
|
||||
}
|
||||
|
||||
if (PB_ATYPE(iter->type) == PB_ATYPE_POINTER && iter->pField != NULL)
|
||||
{
|
||||
iter->pData = *(void**)iter->pField;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->pData = iter->pField;
|
||||
}
|
||||
}
|
||||
|
||||
if (PB_LTYPE_IS_SUBMSG(iter->type))
|
||||
{
|
||||
iter->submsg_desc = iter->descriptor->submsg_info[iter->submessage_index];
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->submsg_desc = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void advance_iterator(pb_field_iter_t *iter)
|
||||
{
|
||||
iter->index++;
|
||||
|
||||
if (iter->index >= iter->descriptor->field_count)
|
||||
{
|
||||
/* Restart */
|
||||
iter->index = 0;
|
||||
iter->field_info_index = 0;
|
||||
iter->submessage_index = 0;
|
||||
iter->required_field_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Increment indexes based on previous field type.
|
||||
* All field info formats have the following fields:
|
||||
* - lowest 2 bits tell the amount of words in the descriptor (2^n words)
|
||||
* - bits 2..7 give the lowest bits of tag number.
|
||||
* - bits 8..15 give the field type.
|
||||
*/
|
||||
uint32_t prev_descriptor = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
|
||||
pb_type_t prev_type = (prev_descriptor >> 8) & 0xFF;
|
||||
pb_size_t descriptor_len = (pb_size_t)(1 << (prev_descriptor & 3));
|
||||
|
||||
/* Add to fields.
|
||||
* The cast to pb_size_t is needed to avoid -Wconversion warning.
|
||||
* Because the data is is constants from generator, there is no danger of overflow.
|
||||
*/
|
||||
iter->field_info_index = (pb_size_t)(iter->field_info_index + descriptor_len);
|
||||
iter->required_field_index = (pb_size_t)(iter->required_field_index + (PB_HTYPE(prev_type) == PB_HTYPE_REQUIRED));
|
||||
iter->submessage_index = (pb_size_t)(iter->submessage_index + PB_LTYPE_IS_SUBMSG(prev_type));
|
||||
}
|
||||
}
|
||||
|
||||
bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message)
|
||||
{
|
||||
memset(iter, 0, sizeof(*iter));
|
||||
|
||||
iter->descriptor = desc;
|
||||
iter->message = message;
|
||||
|
||||
return load_descriptor_values(iter);
|
||||
}
|
||||
|
||||
bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension)
|
||||
{
|
||||
const pb_msgdesc_t *msg = (const pb_msgdesc_t*)extension->type->arg;
|
||||
bool status;
|
||||
|
||||
uint32_t word0 = PB_PROGMEM_READU32(msg->field_info[0]);
|
||||
if (PB_ATYPE(word0 >> 8) == PB_ATYPE_POINTER)
|
||||
{
|
||||
/* For pointer extensions, the pointer is stored directly
|
||||
* in the extension structure. This avoids having an extra
|
||||
* indirection. */
|
||||
status = pb_field_iter_begin(iter, msg, &extension->dest);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = pb_field_iter_begin(iter, msg, extension->dest);
|
||||
}
|
||||
|
||||
iter->pSize = &extension->found;
|
||||
return status;
|
||||
}
|
||||
|
||||
bool pb_field_iter_next(pb_field_iter_t *iter)
|
||||
{
|
||||
advance_iterator(iter);
|
||||
(void)load_descriptor_values(iter);
|
||||
return iter->index != 0;
|
||||
}
|
||||
|
||||
bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag)
|
||||
{
|
||||
if (iter->tag == tag)
|
||||
{
|
||||
return true; /* Nothing to do, correct field already. */
|
||||
}
|
||||
else if (tag > iter->descriptor->largest_tag)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pb_size_t start = iter->index;
|
||||
uint32_t fieldinfo;
|
||||
|
||||
if (tag < iter->tag)
|
||||
{
|
||||
/* Fields are in tag number order, so we know that tag is between
|
||||
* 0 and our start position. Setting index to end forces
|
||||
* advance_iterator() call below to restart from beginning. */
|
||||
iter->index = iter->descriptor->field_count;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* Advance iterator but don't load values yet */
|
||||
advance_iterator(iter);
|
||||
|
||||
/* Do fast check for tag number match */
|
||||
fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
|
||||
|
||||
if (((fieldinfo >> 2) & 0x3F) == (tag & 0x3F))
|
||||
{
|
||||
/* Good candidate, check further */
|
||||
(void)load_descriptor_values(iter);
|
||||
|
||||
if (iter->tag == tag &&
|
||||
PB_LTYPE(iter->type) != PB_LTYPE_EXTENSION)
|
||||
{
|
||||
/* Found it */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} while (iter->index != start);
|
||||
|
||||
/* Searched all the way back to start, and found nothing. */
|
||||
(void)load_descriptor_values(iter);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool pb_field_iter_find_extension(pb_field_iter_t *iter)
|
||||
{
|
||||
if (PB_LTYPE(iter->type) == PB_LTYPE_EXTENSION)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pb_size_t start = iter->index;
|
||||
uint32_t fieldinfo;
|
||||
|
||||
do
|
||||
{
|
||||
/* Advance iterator but don't load values yet */
|
||||
advance_iterator(iter);
|
||||
|
||||
/* Do fast check for field type */
|
||||
fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
|
||||
|
||||
if (PB_LTYPE((fieldinfo >> 8) & 0xFF) == PB_LTYPE_EXTENSION)
|
||||
{
|
||||
return load_descriptor_values(iter);
|
||||
}
|
||||
} while (iter->index != start);
|
||||
|
||||
/* Searched all the way back to start, and found nothing. */
|
||||
(void)load_descriptor_values(iter);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void *pb_const_cast(const void *p)
|
||||
{
|
||||
/* Note: this casts away const, in order to use the common field iterator
|
||||
* logic for both encoding and decoding. The cast is done using union
|
||||
* to avoid spurious compiler warnings. */
|
||||
union {
|
||||
void *p1;
|
||||
const void *p2;
|
||||
} t;
|
||||
t.p2 = p;
|
||||
return t.p1;
|
||||
}
|
||||
|
||||
bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message)
|
||||
{
|
||||
return pb_field_iter_begin(iter, desc, pb_const_cast(message));
|
||||
}
|
||||
|
||||
bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension)
|
||||
{
|
||||
return pb_field_iter_begin_extension(iter, (pb_extension_t*)pb_const_cast(extension));
|
||||
}
|
||||
|
||||
bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field)
|
||||
{
|
||||
if (field->data_size == sizeof(pb_callback_t))
|
||||
{
|
||||
pb_callback_t *pCallback = (pb_callback_t*)field->pData;
|
||||
|
||||
if (pCallback != NULL)
|
||||
{
|
||||
if (istream != NULL && pCallback->funcs.decode != NULL)
|
||||
{
|
||||
return pCallback->funcs.decode(istream, field, &pCallback->arg);
|
||||
}
|
||||
|
||||
if (ostream != NULL && pCallback->funcs.encode != NULL)
|
||||
{
|
||||
return pCallback->funcs.encode(ostream, field, &pCallback->arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true; /* Success, but didn't do anything */
|
||||
|
||||
}
|
||||
|
||||
#ifdef PB_VALIDATE_UTF8
|
||||
|
||||
/* This function checks whether a string is valid UTF-8 text.
|
||||
*
|
||||
* Algorithm is adapted from https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c
|
||||
* Original copyright: Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/> 2005-03-30
|
||||
* Licensed under "Short code license", which allows use under MIT license or
|
||||
* any compatible with it.
|
||||
*/
|
||||
|
||||
bool pb_validate_utf8(const char *str)
|
||||
{
|
||||
const pb_byte_t *s = (const pb_byte_t*)str;
|
||||
while (*s)
|
||||
{
|
||||
if (*s < 0x80)
|
||||
{
|
||||
/* 0xxxxxxx */
|
||||
s++;
|
||||
}
|
||||
else if ((s[0] & 0xe0) == 0xc0)
|
||||
{
|
||||
/* 110XXXXx 10xxxxxx */
|
||||
if ((s[1] & 0xc0) != 0x80 ||
|
||||
(s[0] & 0xfe) == 0xc0) /* overlong? */
|
||||
return false;
|
||||
else
|
||||
s += 2;
|
||||
}
|
||||
else if ((s[0] & 0xf0) == 0xe0)
|
||||
{
|
||||
/* 1110XXXX 10Xxxxxx 10xxxxxx */
|
||||
if ((s[1] & 0xc0) != 0x80 ||
|
||||
(s[2] & 0xc0) != 0x80 ||
|
||||
(s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || /* overlong? */
|
||||
(s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || /* surrogate? */
|
||||
(s[0] == 0xef && s[1] == 0xbf &&
|
||||
(s[2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */
|
||||
return false;
|
||||
else
|
||||
s += 3;
|
||||
}
|
||||
else if ((s[0] & 0xf8) == 0xf0)
|
||||
{
|
||||
/* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */
|
||||
if ((s[1] & 0xc0) != 0x80 ||
|
||||
(s[2] & 0xc0) != 0x80 ||
|
||||
(s[3] & 0xc0) != 0x80 ||
|
||||
(s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || /* overlong? */
|
||||
(s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) /* > U+10FFFF? */
|
||||
return false;
|
||||
else
|
||||
s += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
49
third_party/nanopb/pb_common.h
vendored
Normal file
49
third_party/nanopb/pb_common.h
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* pb_common.h: Common support functions for pb_encode.c and pb_decode.c.
|
||||
* These functions are rarely needed by applications directly.
|
||||
*/
|
||||
|
||||
#ifndef PB_COMMON_H_INCLUDED
|
||||
#define PB_COMMON_H_INCLUDED
|
||||
|
||||
#include "pb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initialize the field iterator structure to beginning.
|
||||
* Returns false if the message type is empty. */
|
||||
bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message);
|
||||
|
||||
/* Get a field iterator for extension field. */
|
||||
bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension);
|
||||
|
||||
/* Same as pb_field_iter_begin(), but for const message pointer.
|
||||
* Note that the pointers in pb_field_iter_t will be non-const but shouldn't
|
||||
* be written to when using these functions. */
|
||||
bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message);
|
||||
bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension);
|
||||
|
||||
/* Advance the iterator to the next field.
|
||||
* Returns false when the iterator wraps back to the first field. */
|
||||
bool pb_field_iter_next(pb_field_iter_t *iter);
|
||||
|
||||
/* Advance the iterator until it points at a field with the given tag.
|
||||
* Returns false if no such field exists. */
|
||||
bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag);
|
||||
|
||||
/* Find a field with type PB_LTYPE_EXTENSION, or return false if not found.
|
||||
* There can be only one extension range field per message. */
|
||||
bool pb_field_iter_find_extension(pb_field_iter_t *iter);
|
||||
|
||||
#ifdef PB_VALIDATE_UTF8
|
||||
/* Validate UTF-8 text string */
|
||||
bool pb_validate_utf8(const char *s);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
1716
third_party/nanopb/pb_decode.c
vendored
Normal file
1716
third_party/nanopb/pb_decode.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
199
third_party/nanopb/pb_decode.h
vendored
Normal file
199
third_party/nanopb/pb_decode.h
vendored
Normal file
|
@ -0,0 +1,199 @@
|
|||
/* pb_decode.h: Functions to decode protocol buffers. Depends on pb_decode.c.
|
||||
* The main function is pb_decode. You also need an input stream, and the
|
||||
* field descriptions created by nanopb_generator.py.
|
||||
*/
|
||||
|
||||
#ifndef PB_DECODE_H_INCLUDED
|
||||
#define PB_DECODE_H_INCLUDED
|
||||
|
||||
#include "pb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Structure for defining custom input streams. You will need to provide
|
||||
* a callback function to read the bytes from your storage, which can be
|
||||
* for example a file or a network socket.
|
||||
*
|
||||
* The callback must conform to these rules:
|
||||
*
|
||||
* 1) Return false on IO errors. This will cause decoding to abort.
|
||||
* 2) You can use state to store your own data (e.g. buffer pointer),
|
||||
* and rely on pb_read to verify that no-body reads past bytes_left.
|
||||
* 3) Your callback may be used with substreams, in which case bytes_left
|
||||
* is different than from the main stream. Don't use bytes_left to compute
|
||||
* any pointers.
|
||||
*/
|
||||
struct pb_istream_s
|
||||
{
|
||||
#ifdef PB_BUFFER_ONLY
|
||||
/* Callback pointer is not used in buffer-only configuration.
|
||||
* Having an int pointer here allows binary compatibility but
|
||||
* gives an error if someone tries to assign callback function.
|
||||
*/
|
||||
int *callback;
|
||||
#else
|
||||
bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count);
|
||||
#endif
|
||||
|
||||
void *state; /* Free field for use by callback implementation */
|
||||
size_t bytes_left;
|
||||
|
||||
#ifndef PB_NO_ERRMSG
|
||||
const char *errmsg;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef PB_NO_ERRMSG
|
||||
#define PB_ISTREAM_EMPTY {0,0,0,0}
|
||||
#else
|
||||
#define PB_ISTREAM_EMPTY {0,0,0}
|
||||
#endif
|
||||
|
||||
/***************************
|
||||
* Main decoding functions *
|
||||
***************************/
|
||||
|
||||
/* Decode a single protocol buffers message from input stream into a C structure.
|
||||
* Returns true on success, false on any failure.
|
||||
* The actual struct pointed to by dest must match the description in fields.
|
||||
* Callback fields of the destination structure must be initialized by caller.
|
||||
* All other fields will be initialized by this function.
|
||||
*
|
||||
* Example usage:
|
||||
* MyMessage msg = {};
|
||||
* uint8_t buffer[64];
|
||||
* pb_istream_t stream;
|
||||
*
|
||||
* // ... read some data into buffer ...
|
||||
*
|
||||
* stream = pb_istream_from_buffer(buffer, count);
|
||||
* pb_decode(&stream, MyMessage_fields, &msg);
|
||||
*/
|
||||
bool pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct);
|
||||
|
||||
/* Extended version of pb_decode, with several options to control
|
||||
* the decoding process:
|
||||
*
|
||||
* PB_DECODE_NOINIT: Do not initialize the fields to default values.
|
||||
* This is slightly faster if you do not need the default
|
||||
* values and instead initialize the structure to 0 using
|
||||
* e.g. memset(). This can also be used for merging two
|
||||
* messages, i.e. combine already existing data with new
|
||||
* values.
|
||||
*
|
||||
* PB_DECODE_DELIMITED: Input message starts with the message size as varint.
|
||||
* Corresponds to parseDelimitedFrom() in Google's
|
||||
* protobuf API.
|
||||
*
|
||||
* PB_DECODE_NULLTERMINATED: Stop reading when field tag is read as 0. This allows
|
||||
* reading null terminated messages.
|
||||
* NOTE: Until nanopb-0.4.0, pb_decode() also allows
|
||||
* null-termination. This behaviour is not supported in
|
||||
* most other protobuf implementations, so PB_DECODE_DELIMITED
|
||||
* is a better option for compatibility.
|
||||
*
|
||||
* Multiple flags can be combined with bitwise or (| operator)
|
||||
*/
|
||||
#define PB_DECODE_NOINIT 0x01U
|
||||
#define PB_DECODE_DELIMITED 0x02U
|
||||
#define PB_DECODE_NULLTERMINATED 0x04U
|
||||
bool pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags);
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define pb_decode_noinit(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_NOINIT)
|
||||
#define pb_decode_delimited(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_DELIMITED)
|
||||
#define pb_decode_delimited_noinit(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_DELIMITED | PB_DECODE_NOINIT)
|
||||
#define pb_decode_nullterminated(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_NULLTERMINATED)
|
||||
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
/* Release any allocated pointer fields. If you use dynamic allocation, you should
|
||||
* call this for any successfully decoded message when you are done with it. If
|
||||
* pb_decode() returns with an error, the message is already released.
|
||||
*/
|
||||
void pb_release(const pb_msgdesc_t *fields, void *dest_struct);
|
||||
#else
|
||||
/* Allocation is not supported, so release is no-op */
|
||||
#define pb_release(fields, dest_struct) PB_UNUSED(fields); PB_UNUSED(dest_struct);
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************
|
||||
* Functions for manipulating streams *
|
||||
**************************************/
|
||||
|
||||
/* Create an input stream for reading from a memory buffer.
|
||||
*
|
||||
* msglen should be the actual length of the message, not the full size of
|
||||
* allocated buffer.
|
||||
*
|
||||
* Alternatively, you can use a custom stream that reads directly from e.g.
|
||||
* a file or a network socket.
|
||||
*/
|
||||
pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t msglen);
|
||||
|
||||
/* Function to read from a pb_istream_t. You can use this if you need to
|
||||
* read some custom header data, or to read data in field callbacks.
|
||||
*/
|
||||
bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count);
|
||||
|
||||
|
||||
/************************************************
|
||||
* Helper functions for writing field callbacks *
|
||||
************************************************/
|
||||
|
||||
/* Decode the tag for the next field in the stream. Gives the wire type and
|
||||
* field tag. At end of the message, returns false and sets eof to true. */
|
||||
bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof);
|
||||
|
||||
/* Skip the field payload data, given the wire type. */
|
||||
bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type);
|
||||
|
||||
/* Decode an integer in the varint format. This works for enum, int32,
|
||||
* int64, uint32 and uint64 field types. */
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest);
|
||||
#else
|
||||
#define pb_decode_varint pb_decode_varint32
|
||||
#endif
|
||||
|
||||
/* Decode an integer in the varint format. This works for enum, int32,
|
||||
* and uint32 field types. */
|
||||
bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest);
|
||||
|
||||
/* Decode a bool value in varint format. */
|
||||
bool pb_decode_bool(pb_istream_t *stream, bool *dest);
|
||||
|
||||
/* Decode an integer in the zig-zagged svarint format. This works for sint32
|
||||
* and sint64. */
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest);
|
||||
#else
|
||||
bool pb_decode_svarint(pb_istream_t *stream, int32_t *dest);
|
||||
#endif
|
||||
|
||||
/* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to
|
||||
* a 4-byte wide C variable. */
|
||||
bool pb_decode_fixed32(pb_istream_t *stream, void *dest);
|
||||
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
/* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to
|
||||
* a 8-byte wide C variable. */
|
||||
bool pb_decode_fixed64(pb_istream_t *stream, void *dest);
|
||||
#endif
|
||||
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
/* Decode a double value into float variable. */
|
||||
bool pb_decode_double_as_float(pb_istream_t *stream, float *dest);
|
||||
#endif
|
||||
|
||||
/* Make a limited-length substream for reading a PB_WT_STRING field. */
|
||||
bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream);
|
||||
bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
1000
third_party/nanopb/pb_encode.c
vendored
Normal file
1000
third_party/nanopb/pb_encode.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
185
third_party/nanopb/pb_encode.h
vendored
Normal file
185
third_party/nanopb/pb_encode.h
vendored
Normal file
|
@ -0,0 +1,185 @@
|
|||
/* pb_encode.h: Functions to encode protocol buffers. Depends on pb_encode.c.
|
||||
* The main function is pb_encode. You also need an output stream, and the
|
||||
* field descriptions created by nanopb_generator.py.
|
||||
*/
|
||||
|
||||
#ifndef PB_ENCODE_H_INCLUDED
|
||||
#define PB_ENCODE_H_INCLUDED
|
||||
|
||||
#include "pb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Structure for defining custom output streams. You will need to provide
|
||||
* a callback function to write the bytes to your storage, which can be
|
||||
* for example a file or a network socket.
|
||||
*
|
||||
* The callback must conform to these rules:
|
||||
*
|
||||
* 1) Return false on IO errors. This will cause encoding to abort.
|
||||
* 2) You can use state to store your own data (e.g. buffer pointer).
|
||||
* 3) pb_write will update bytes_written after your callback runs.
|
||||
* 4) Substreams will modify max_size and bytes_written. Don't use them
|
||||
* to calculate any pointers.
|
||||
*/
|
||||
struct pb_ostream_s
|
||||
{
|
||||
#ifdef PB_BUFFER_ONLY
|
||||
/* Callback pointer is not used in buffer-only configuration.
|
||||
* Having an int pointer here allows binary compatibility but
|
||||
* gives an error if someone tries to assign callback function.
|
||||
* Also, NULL pointer marks a 'sizing stream' that does not
|
||||
* write anything.
|
||||
*/
|
||||
const int *callback;
|
||||
#else
|
||||
bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
|
||||
#endif
|
||||
void *state; /* Free field for use by callback implementation. */
|
||||
size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */
|
||||
size_t bytes_written; /* Number of bytes written so far. */
|
||||
|
||||
#ifndef PB_NO_ERRMSG
|
||||
const char *errmsg;
|
||||
#endif
|
||||
};
|
||||
|
||||
/***************************
|
||||
* Main encoding functions *
|
||||
***************************/
|
||||
|
||||
/* Encode a single protocol buffers message from C structure into a stream.
|
||||
* Returns true on success, false on any failure.
|
||||
* The actual struct pointed to by src_struct must match the description in fields.
|
||||
* All required fields in the struct are assumed to have been filled in.
|
||||
*
|
||||
* Example usage:
|
||||
* MyMessage msg = {};
|
||||
* uint8_t buffer[64];
|
||||
* pb_ostream_t stream;
|
||||
*
|
||||
* msg.field1 = 42;
|
||||
* stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
* pb_encode(&stream, MyMessage_fields, &msg);
|
||||
*/
|
||||
bool pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct);
|
||||
|
||||
/* Extended version of pb_encode, with several options to control the
|
||||
* encoding process:
|
||||
*
|
||||
* PB_ENCODE_DELIMITED: Prepend the length of message as a varint.
|
||||
* Corresponds to writeDelimitedTo() in Google's
|
||||
* protobuf API.
|
||||
*
|
||||
* PB_ENCODE_NULLTERMINATED: Append a null byte to the message for termination.
|
||||
* NOTE: This behaviour is not supported in most other
|
||||
* protobuf implementations, so PB_ENCODE_DELIMITED
|
||||
* is a better option for compatibility.
|
||||
*/
|
||||
#define PB_ENCODE_DELIMITED 0x02U
|
||||
#define PB_ENCODE_NULLTERMINATED 0x04U
|
||||
bool pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags);
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define pb_encode_delimited(s,f,d) pb_encode_ex(s,f,d, PB_ENCODE_DELIMITED)
|
||||
#define pb_encode_nullterminated(s,f,d) pb_encode_ex(s,f,d, PB_ENCODE_NULLTERMINATED)
|
||||
|
||||
/* Encode the message to get the size of the encoded data, but do not store
|
||||
* the data. */
|
||||
bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct);
|
||||
|
||||
/**************************************
|
||||
* Functions for manipulating streams *
|
||||
**************************************/
|
||||
|
||||
/* Create an output stream for writing into a memory buffer.
|
||||
* The number of bytes written can be found in stream.bytes_written after
|
||||
* encoding the message.
|
||||
*
|
||||
* Alternatively, you can use a custom stream that writes directly to e.g.
|
||||
* a file or a network socket.
|
||||
*/
|
||||
pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize);
|
||||
|
||||
/* Pseudo-stream for measuring the size of a message without actually storing
|
||||
* the encoded data.
|
||||
*
|
||||
* Example usage:
|
||||
* MyMessage msg = {};
|
||||
* pb_ostream_t stream = PB_OSTREAM_SIZING;
|
||||
* pb_encode(&stream, MyMessage_fields, &msg);
|
||||
* printf("Message size is %d\n", stream.bytes_written);
|
||||
*/
|
||||
#ifndef PB_NO_ERRMSG
|
||||
#define PB_OSTREAM_SIZING {0,0,0,0,0}
|
||||
#else
|
||||
#define PB_OSTREAM_SIZING {0,0,0,0}
|
||||
#endif
|
||||
|
||||
/* Function to write into a pb_ostream_t stream. You can use this if you need
|
||||
* to append or prepend some custom headers to the message.
|
||||
*/
|
||||
bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
|
||||
|
||||
|
||||
/************************************************
|
||||
* Helper functions for writing field callbacks *
|
||||
************************************************/
|
||||
|
||||
/* Encode field header based on type and field number defined in the field
|
||||
* structure. Call this from the callback before writing out field contents. */
|
||||
bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_iter_t *field);
|
||||
|
||||
/* Encode field header by manually specifying wire type. You need to use this
|
||||
* if you want to write out packed arrays from a callback field. */
|
||||
bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number);
|
||||
|
||||
/* Encode an integer in the varint format.
|
||||
* This works for bool, enum, int32, int64, uint32 and uint64 field types. */
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
bool pb_encode_varint(pb_ostream_t *stream, uint64_t value);
|
||||
#else
|
||||
bool pb_encode_varint(pb_ostream_t *stream, uint32_t value);
|
||||
#endif
|
||||
|
||||
/* Encode an integer in the zig-zagged svarint format.
|
||||
* This works for sint32 and sint64. */
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
bool pb_encode_svarint(pb_ostream_t *stream, int64_t value);
|
||||
#else
|
||||
bool pb_encode_svarint(pb_ostream_t *stream, int32_t value);
|
||||
#endif
|
||||
|
||||
/* Encode a string or bytes type field. For strings, pass strlen(s) as size. */
|
||||
bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size);
|
||||
|
||||
/* Encode a fixed32, sfixed32 or float value.
|
||||
* You need to pass a pointer to a 4-byte wide C variable. */
|
||||
bool pb_encode_fixed32(pb_ostream_t *stream, const void *value);
|
||||
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
/* Encode a fixed64, sfixed64 or double value.
|
||||
* You need to pass a pointer to a 8-byte wide C variable. */
|
||||
bool pb_encode_fixed64(pb_ostream_t *stream, const void *value);
|
||||
#endif
|
||||
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
/* Encode a float value so that it appears like a double in the encoded
|
||||
* message. */
|
||||
bool pb_encode_float_as_double(pb_ostream_t *stream, float value);
|
||||
#endif
|
||||
|
||||
/* Encode a submessage field.
|
||||
* You need to pass the pb_field_t array and pointer to struct, just like
|
||||
* with pb_encode(). This internally encodes the submessage twice, first to
|
||||
* calculate message size and then to actually write it out.
|
||||
*/
|
||||
bool pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
3
third_party/nanopb/spm-test/objc/c-header.c
vendored
Normal file
3
third_party/nanopb/spm-test/objc/c-header.c
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
#include "pb.h"
|
||||
#include "pb_common.h"
|
||||
#include "pb_decode.h"
|
3
third_party/nanopb/spm-test/objc/objc-header.m
vendored
Normal file
3
third_party/nanopb/spm-test/objc/objc-header.m
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
#import "pb.h"
|
||||
#import <pb_common.h>
|
||||
#include "pb_decode.h"
|
1
third_party/nanopb/spm-test/objc/objc-module.m
vendored
Normal file
1
third_party/nanopb/spm-test/objc/objc-module.m
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
@import nanopb;
|
3
third_party/nanopb/spm-test/objc/objc-qualified.m
vendored
Normal file
3
third_party/nanopb/spm-test/objc/objc-qualified.m
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
#import "nanopb/pb.h"
|
||||
#import <nanopb/pb_common.h>
|
||||
#include "nanopb/pb_decode.h"
|
1
third_party/nanopb/spm-test/swift/main.swift
vendored
Normal file
1
third_party/nanopb/spm-test/swift/main.swift
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
import nanopb
|
1
third_party/nanopb/spm_headers/nanopb/pb.h
vendored
Symbolic link
1
third_party/nanopb/spm_headers/nanopb/pb.h
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../pb.h
|
1
third_party/nanopb/spm_headers/nanopb/pb_common.h
vendored
Symbolic link
1
third_party/nanopb/spm_headers/nanopb/pb_common.h
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../pb_common.h
|
1
third_party/nanopb/spm_headers/nanopb/pb_decode.h
vendored
Symbolic link
1
third_party/nanopb/spm_headers/nanopb/pb_decode.h
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../pb_decode.h
|
1
third_party/nanopb/spm_headers/nanopb/pb_encode.h
vendored
Symbolic link
1
third_party/nanopb/spm_headers/nanopb/pb_encode.h
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../pb_encode.h
|
1
third_party/nanopb/spm_headers/pb.h
vendored
Normal file
1
third_party/nanopb/spm_headers/pb.h
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
#include "nanopb/pb.h"
|
1
third_party/nanopb/spm_headers/pb_common.h
vendored
Normal file
1
third_party/nanopb/spm_headers/pb_common.h
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
#include "nanopb/pb_common.h"
|
1
third_party/nanopb/spm_headers/pb_decode.h
vendored
Normal file
1
third_party/nanopb/spm_headers/pb_decode.h
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
#include "nanopb/pb_decode.h"
|
1
third_party/nanopb/spm_headers/pb_encode.h
vendored
Normal file
1
third_party/nanopb/spm_headers/pb_encode.h
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
#include "nanopb/pb_encode.h"
|
21
third_party/nanopb/tests/Makefile
vendored
Normal file
21
third_party/nanopb/tests/Makefile
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
all:
|
||||
scons
|
||||
|
||||
clean:
|
||||
scons -c
|
||||
|
||||
coverage:
|
||||
rm -rf build coverage
|
||||
|
||||
# LCOV does not like the newer gcov format
|
||||
scons CC=gcc-4.6 CXX=gcc-4.6
|
||||
|
||||
# Collect the data
|
||||
mkdir build/coverage
|
||||
lcov --base-directory . --directory build/ --gcov-tool gcov-4.6 -c -o build/coverage/nanopb.info
|
||||
|
||||
# Remove the test code from results
|
||||
lcov -r build/coverage/nanopb.info '*tests*' -o build/coverage/nanopb.info
|
||||
|
||||
# Generate HTML
|
||||
genhtml -o build/coverage build/coverage/nanopb.info
|
240
third_party/nanopb/tests/SConstruct
vendored
Normal file
240
third_party/nanopb/tests/SConstruct
vendored
Normal file
|
@ -0,0 +1,240 @@
|
|||
Help('''
|
||||
Type 'scons' to build and run all the available test cases.
|
||||
It will automatically detect your platform and C compiler and
|
||||
build appropriately.
|
||||
|
||||
You can modify the behaviour using following options:
|
||||
BUILDDIR Directory to build into (default "build")
|
||||
CC Name of C compiler
|
||||
CXX Name of C++ compiler
|
||||
CCFLAGS Flags to pass to the C compiler
|
||||
CXXFLAGS Flags to pass to the C++ compiler
|
||||
LINK Name of linker (usually same as CC)
|
||||
LINKFLAGS Flags to pass to linker
|
||||
LINKLIBS Flags to pass to linker after object files
|
||||
PROTOC Path to protoc binary
|
||||
PROTOCFLAGS Arguments to pass protoc
|
||||
NODEFARGS Do not add the default CCFLAGS
|
||||
NOVALGRIND Do not use valgrind for memory checks
|
||||
|
||||
For example, for a clang build, use:
|
||||
scons CC=clang CXX=clang++
|
||||
''')
|
||||
|
||||
import os
|
||||
import platform
|
||||
env = Environment(ENV = os.environ)
|
||||
|
||||
# Allow giving environment flags on command line.
|
||||
list_vars = ['CCFLAGS', 'CXXFLAGS', 'LINKFLAGS', 'LINKLIBS', 'PROTOCFLAGS']
|
||||
for var,val in ARGUMENTS.items():
|
||||
if var in list_vars:
|
||||
env.Append(**{var: val})
|
||||
else:
|
||||
env.Replace(**{var: val})
|
||||
|
||||
env.SetDefault(BUILDDIR = "build")
|
||||
env.SConsignFile(env['BUILDDIR'] + "/sconsign")
|
||||
env.Replace(CONFIGUREDIR = env['BUILDDIR'] + "/config")
|
||||
|
||||
# If a cross compilation platform is given, apply the environment settings
|
||||
# from site_scons/platforms/X/X.py
|
||||
if ARGUMENTS.get('PLATFORM'):
|
||||
platform_func = platforms.get(ARGUMENTS.get('PLATFORM'))
|
||||
if not platform_func:
|
||||
print("Supported platforms: " + str(platforms.keys()))
|
||||
raise Exception("Unsupported platform: " + ARGUMENTS.get('PLATFORM'))
|
||||
else:
|
||||
platform_func(env)
|
||||
|
||||
# Load nanopb generator build rules from site_scons/site_tools/nanopb.py
|
||||
env.Tool("nanopb")
|
||||
|
||||
# Limit memory usage. This is to catch problems like issue #338
|
||||
try:
|
||||
import resource
|
||||
soft, hard = resource.getrlimit(resourse.RLIMIT_AS)
|
||||
resource.setrlimit(resource.RLIMIT_AS, (100*1024*1024, hard))
|
||||
except:
|
||||
pass
|
||||
|
||||
# On Mac OS X, gcc is usually alias for clang.
|
||||
# To avoid problem with default options, use clang directly.
|
||||
if platform.system() == "Darwin" and 'CC' not in ARGUMENTS:
|
||||
env.Replace(CC = "clang", CXX = "clang++")
|
||||
|
||||
# Add the builders defined in site_init.py
|
||||
add_nanopb_builders(env)
|
||||
|
||||
# Path to the files shared by tests, and to the nanopb core.
|
||||
env.Append(CPPPATH = ["#../", "$COMMON"])
|
||||
|
||||
# Path for finding nanopb.proto
|
||||
env.Append(PROTOCPATH = '#../generator')
|
||||
|
||||
# Check the compilation environment, unless we are just cleaning up.
|
||||
if not env.GetOption('clean'):
|
||||
def check_ccflags(context, flags, linkflags = ''):
|
||||
'''Check if given CCFLAGS are supported'''
|
||||
context.Message('Checking support for CCFLAGS="%s"... ' % flags)
|
||||
oldflags = context.env['CCFLAGS']
|
||||
oldlinkflags = context.env['LINKFLAGS']
|
||||
context.env.Append(CCFLAGS = flags)
|
||||
context.env.Append(LINKFLAGS = linkflags)
|
||||
result = context.TryCompile("int main() {return 0;}", '.c')
|
||||
context.env.Replace(CCFLAGS = oldflags)
|
||||
context.env.Replace(LINKFLAGS = oldlinkflags)
|
||||
context.Result(result)
|
||||
return result
|
||||
|
||||
def check_protocversion(context):
|
||||
context.Display("Checking protoc version... ")
|
||||
status, output = context.TryAction('$PROTOC --version > $TARGET')
|
||||
if status:
|
||||
context.Result(str(output.strip()))
|
||||
return str(output.strip())
|
||||
else:
|
||||
context.Display("error: %s\n" % output.strip())
|
||||
context.did_show_result = 1
|
||||
context.Result("unknown, assuming 3.6.1")
|
||||
return "3.6.1"
|
||||
|
||||
conf = Configure(env, custom_tests =
|
||||
{'CheckCCFLAGS': check_ccflags,
|
||||
'CheckProtocVersion': check_protocversion})
|
||||
|
||||
# If the platform doesn't support C99, use our own header file instead.
|
||||
stdbool = conf.CheckCHeader('stdbool.h')
|
||||
stdint = conf.CheckCHeader('stdint.h')
|
||||
stddef = conf.CheckCHeader('stddef.h')
|
||||
string = conf.CheckCHeader('string.h')
|
||||
stdlib = conf.CheckCHeader('stdlib.h')
|
||||
limits = conf.CheckCHeader('limits.h')
|
||||
if not stdbool or not stdint or not stddef or not string or not limits:
|
||||
conf.env.Append(CPPDEFINES = {'PB_SYSTEM_HEADER': '\\"pb_syshdr.h\\"'})
|
||||
conf.env.Append(CPPPATH = "#../extra")
|
||||
conf.env.Append(SYSHDR = '\\"pb_syshdr.h\\"')
|
||||
|
||||
if stdbool: conf.env.Append(CPPDEFINES = {'HAVE_STDBOOL_H': 1})
|
||||
if stdint: conf.env.Append(CPPDEFINES = {'HAVE_STDINT_H': 1})
|
||||
if stddef: conf.env.Append(CPPDEFINES = {'HAVE_STDDEF_H': 1})
|
||||
if string: conf.env.Append(CPPDEFINES = {'HAVE_STRING_H': 1})
|
||||
if stdlib: conf.env.Append(CPPDEFINES = {'HAVE_STDLIB_H': 1})
|
||||
if limits: conf.env.Append(CPPDEFINES = {'HAVE_LIMITS_H': 1})
|
||||
|
||||
# Check protoc version
|
||||
conf.env['PROTOC_VERSION'] = conf.CheckProtocVersion()
|
||||
|
||||
# Initialize compiler arguments with defaults, unless overridden on
|
||||
# command line.
|
||||
if not env.get('NODEFARGS'):
|
||||
# Check if libmudflap is available (only with GCC)
|
||||
if 'gcc' in env['CC']:
|
||||
if conf.CheckLib('mudflap'):
|
||||
conf.env.Append(CCFLAGS = '-fmudflap')
|
||||
conf.env.Append(LINKFLAGS = '-fmudflap')
|
||||
|
||||
# Check if we can use extra strict warning flags (only with GCC)
|
||||
extra = '-Wcast-qual -Wlogical-op -Wconversion'
|
||||
extra += ' -fstrict-aliasing -Wstrict-aliasing=1'
|
||||
extra += ' -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls'
|
||||
extra += ' -Wstack-protector '
|
||||
if 'gcc' in env['CC']:
|
||||
if conf.CheckCCFLAGS(extra):
|
||||
conf.env.Append(CORECFLAGS = extra)
|
||||
|
||||
# Check if we can use undefined behaviour sanitizer (only with clang)
|
||||
# TODO: Fuzz test triggers the bool sanitizer, figure out whether to
|
||||
# modify the fuzz test or to keep ignoring the check.
|
||||
extra = '-fsanitize=undefined,integer -fno-sanitize-recover=undefined,integer '
|
||||
if 'clang' in env['CC']:
|
||||
if conf.CheckCCFLAGS(extra, linkflags = extra):
|
||||
conf.env.Append(CORECFLAGS = extra)
|
||||
conf.env.Append(LINKFLAGS = extra)
|
||||
|
||||
# End the config stuff
|
||||
env = conf.Finish()
|
||||
|
||||
if not env.get('NODEFARGS'):
|
||||
# Initialize the CCFLAGS according to the compiler
|
||||
if 'gcc' in env['CC']:
|
||||
# GNU Compiler Collection
|
||||
|
||||
# Debug info, warnings as errors
|
||||
env.Append(CFLAGS = '-g -Wall -Werror ')
|
||||
env.Append(CORECFLAGS = '-Wextra ')
|
||||
|
||||
# Pedantic ANSI C. On AVR this doesn't work because we use large
|
||||
# enums in some of the tests.
|
||||
if env.get("EMBEDDED") != "AVR":
|
||||
env.Append(CFLAGS = '-ansi ')
|
||||
env.Append(CORECFLAGS = '-pedantic ')
|
||||
|
||||
# Profiling and coverage
|
||||
if not env.get("EMBEDDED"):
|
||||
env.Append(CFLAGS = '-fprofile-arcs -ftest-coverage ')
|
||||
env.Append(LINKFLAGS = '-g --coverage')
|
||||
|
||||
|
||||
# We currently need uint64_t anyway, even though ANSI C90 otherwise..
|
||||
env.Append(CFLAGS = '-Wno-long-long')
|
||||
elif 'clang' in env['CC']:
|
||||
# CLang
|
||||
env.Append(CFLAGS = '-ansi -g -Wall -Werror')
|
||||
env.Append(CORECFLAGS = ' -Wextra -Wcast-qual -Wconversion')
|
||||
elif 'cl' in env['CC']:
|
||||
# Microsoft Visual C++
|
||||
|
||||
# Debug info on, warning level 2 for tests, warnings as errors
|
||||
env.Append(CFLAGS = '/Zi /W2 /WX')
|
||||
env.Append(LINKFLAGS = '/DEBUG')
|
||||
|
||||
# More strict checks on the nanopb core
|
||||
env.Append(CORECFLAGS = '/W4')
|
||||
|
||||
# Enable C11 standard
|
||||
env.Append(CFLAGS = ' /std:c11 ')
|
||||
|
||||
# Disable warning about sizeof(union{}) construct that is used in
|
||||
# message size macros, in e.g. multiple_files testcase. The C construct
|
||||
# itself is valid, but quite rare, which causes Visual C++ to give a warning
|
||||
# about it.
|
||||
env.Append(CFLAGS = '/wd4116')
|
||||
elif 'tcc' in env['CC']:
|
||||
# Tiny C Compiler
|
||||
env.Append(CFLAGS = '-Wall -Werror -g')
|
||||
|
||||
if 'clang' in env['CXX']:
|
||||
env.Append(CXXFLAGS = '-g -Wall -Werror -Wextra -Wno-missing-field-initializers')
|
||||
elif 'g++' in env['CXX'] or 'gcc' in env['CXX']:
|
||||
env.Append(CXXFLAGS = '-g -Wall -Werror -Wextra -Wno-missing-field-initializers -std=gnu++11')
|
||||
elif 'cl' in env['CXX']:
|
||||
env.Append(CXXFLAGS = '/Zi /W2 /WX /wd4116 /wd4127')
|
||||
|
||||
env.SetDefault(CORECFLAGS = '')
|
||||
|
||||
if not env.get("EMBEDDED") and not env.get("NOVALGRIND"):
|
||||
valgrind = env.WhereIs('valgrind')
|
||||
if valgrind:
|
||||
env.SetDefault(VALGRIND = valgrind)
|
||||
|
||||
# Make it possible to add commands to the end of linker line
|
||||
env.SetDefault(LINKLIBS = '')
|
||||
env.Replace(LINKCOM = env['LINKCOM'] + " $LINKLIBS")
|
||||
|
||||
# Place build files under separate folder
|
||||
import os.path
|
||||
env['VARIANT_DIR'] = env['BUILDDIR']
|
||||
env['BUILD'] = '#' + env['VARIANT_DIR']
|
||||
env['COMMON'] = '#' + env['VARIANT_DIR'] + '/common'
|
||||
|
||||
# Include common/SConscript first to make sure its exports are available
|
||||
# to other SConscripts.
|
||||
SConscript("common/SConscript", exports = 'env', variant_dir = env['VARIANT_DIR'] + '/common')
|
||||
|
||||
# Now include the SConscript files from all subdirectories
|
||||
for subdir in Glob('*/SConscript') + Glob('regression/*/SConscript'):
|
||||
if str(subdir).startswith("common/"): continue
|
||||
if str(subdir).startswith("common\\"): continue
|
||||
SConscript(subdir, exports = 'env', variant_dir = env['VARIANT_DIR'] + '/' + os.path.dirname(str(subdir)))
|
||||
|
45
third_party/nanopb/tests/alltypes/SConscript
vendored
Normal file
45
third_party/nanopb/tests/alltypes/SConscript
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Build and run a test that encodes and decodes a message that contains
|
||||
# all of the Protocol Buffers data types.
|
||||
|
||||
Import("env")
|
||||
|
||||
env.NanopbProto(["alltypes", "alltypes.options"])
|
||||
enc = env.Program(["encode_alltypes.c", "alltypes.pb.c", "$COMMON/pb_encode.o", "$COMMON/pb_common.o"])
|
||||
dec = env.Program(["decode_alltypes.c", "alltypes.pb.c", "$COMMON/pb_decode.o", "$COMMON/pb_common.o"])
|
||||
|
||||
# Test the round-trip from nanopb encoder to nanopb decoder
|
||||
env.RunTest(enc)
|
||||
env.RunTest([dec, "encode_alltypes.output"])
|
||||
|
||||
# Re-encode the data using protoc, and check that the results from nanopb
|
||||
# match byte-per-byte to the protoc output.
|
||||
env.Decode("encode_alltypes.output.decoded",
|
||||
["encode_alltypes.output", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Encode("encode_alltypes.output.recoded",
|
||||
["encode_alltypes.output.decoded", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Compare(["encode_alltypes.output", "encode_alltypes.output.recoded"])
|
||||
|
||||
# Do the same checks with the optional fields present.
|
||||
env.RunTest("optionals.output", enc, ARGS = ['1'])
|
||||
env.RunTest("optionals.decout", [dec, "optionals.output"], ARGS = ['1'])
|
||||
env.Decode("optionals.output.decoded",
|
||||
["optionals.output", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Encode("optionals.output.recoded",
|
||||
["optionals.output.decoded", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Compare(["optionals.output", "optionals.output.recoded"])
|
||||
|
||||
# And for the _zero initializer
|
||||
env.RunTest("zeroinit.output", enc, ARGS = ['2'])
|
||||
env.RunTest("zeroinit.decout", [dec, "zeroinit.output"], ARGS = ['2'])
|
||||
env.Decode("zeroinit.output.decoded",
|
||||
["zeroinit.output", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Encode("zeroinit.output.recoded",
|
||||
["zeroinit.output.decoded", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Compare(["zeroinit.output", "zeroinit.output.recoded"])
|
||||
|
8
third_party/nanopb/tests/alltypes/alltypes.options
vendored
Normal file
8
third_party/nanopb/tests/alltypes/alltypes.options
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
* max_size:16
|
||||
* max_count:5
|
||||
*.*fbytes fixed_length:true max_size:4
|
||||
*.*farray fixed_count:true max_count:5
|
||||
*.*farray2 fixed_count:true max_count:3
|
||||
IntSizes.*int8 int_size:IS_8
|
||||
IntSizes.*int16 int_size:IS_16
|
||||
DescriptorSize8 descriptorsize:DS_8
|
166
third_party/nanopb/tests/alltypes/alltypes.proto
vendored
Normal file
166
third_party/nanopb/tests/alltypes/alltypes.proto
vendored
Normal file
|
@ -0,0 +1,166 @@
|
|||
syntax = "proto2";
|
||||
// package name placeholder
|
||||
|
||||
enum NonZeroBasedEnum {
|
||||
Two = 2;
|
||||
Three = 3;
|
||||
Four = 4;
|
||||
}
|
||||
|
||||
message SubMessage {
|
||||
required string substuff1 = 1 [default = "1"];
|
||||
required int32 substuff2 = 2 [default = 2];
|
||||
optional fixed32 substuff3 = 3 [default = 3];
|
||||
}
|
||||
|
||||
message EmptyMessage {
|
||||
|
||||
}
|
||||
|
||||
enum HugeEnum {
|
||||
Negative = -2147483647; /* protoc doesn't accept -2147483648 here */
|
||||
Positive = 2147483647;
|
||||
}
|
||||
|
||||
message Limits {
|
||||
required int32 int32_min = 1 [default = 2147483647];
|
||||
required int32 int32_max = 2 [default = -2147483647];
|
||||
required uint32 uint32_min = 3 [default = 4294967295];
|
||||
required uint32 uint32_max = 4 [default = 0];
|
||||
required int64 int64_min = 5 [default = 9223372036854775807];
|
||||
required int64 int64_max = 6 [default = -9223372036854775807];
|
||||
required uint64 uint64_min = 7 [default = 18446744073709551615];
|
||||
required uint64 uint64_max = 8 [default = 0];
|
||||
required HugeEnum enum_min = 9 [default = Positive];
|
||||
required HugeEnum enum_max = 10 [default = Negative];
|
||||
required int32 largetag = 65535 [default = 0];
|
||||
}
|
||||
|
||||
message IntSizes {
|
||||
required int32 req_int8 = 1 ;
|
||||
required uint32 req_uint8 = 2 ;
|
||||
required sint32 req_sint8 = 3 ;
|
||||
required int32 req_int16 = 4 ;
|
||||
required uint32 req_uint16 = 5 ;
|
||||
required sint32 req_sint16 = 6 ;
|
||||
}
|
||||
|
||||
message DescriptorSize8 {
|
||||
required int32 first = 1;
|
||||
required int32 second = 22222;
|
||||
}
|
||||
|
||||
enum MyEnum {
|
||||
Zero = 0;
|
||||
First = 1;
|
||||
Second = 2;
|
||||
Truth = 42;
|
||||
}
|
||||
|
||||
message AllTypes {
|
||||
required int32 req_int32 = 1;
|
||||
required int64 req_int64 = 2;
|
||||
required uint32 req_uint32 = 3;
|
||||
required uint64 req_uint64 = 4;
|
||||
required sint32 req_sint32 = 5;
|
||||
required sint64 req_sint64 = 6;
|
||||
required bool req_bool = 7;
|
||||
|
||||
required fixed32 req_fixed32 = 8;
|
||||
required sfixed32 req_sfixed32= 9;
|
||||
required float req_float = 10;
|
||||
|
||||
required fixed64 req_fixed64 = 11;
|
||||
required sfixed64 req_sfixed64= 12;
|
||||
required double req_double = 13;
|
||||
|
||||
required string req_string = 14;
|
||||
required bytes req_bytes = 15;
|
||||
required SubMessage req_submsg = 16;
|
||||
required MyEnum req_enum = 17;
|
||||
required EmptyMessage req_emptymsg = 18;
|
||||
required bytes req_fbytes = 19;
|
||||
|
||||
repeated int32 rep_int32 = 21 [packed = true];
|
||||
repeated int64 rep_int64 = 22 [packed = true];
|
||||
repeated uint32 rep_uint32 = 23 [packed = true];
|
||||
repeated uint64 rep_uint64 = 24 [packed = true];
|
||||
repeated sint32 rep_sint32 = 25 [packed = true];
|
||||
repeated sint64 rep_sint64 = 26 [packed = true];
|
||||
repeated bool rep_bool = 27 [packed = true];
|
||||
|
||||
repeated fixed32 rep_fixed32 = 28 [packed = true];
|
||||
repeated sfixed32 rep_sfixed32= 29 [packed = true];
|
||||
repeated float rep_float = 30 [packed = true];
|
||||
|
||||
repeated fixed64 rep_fixed64 = 31 [packed = true];
|
||||
repeated sfixed64 rep_sfixed64= 32 [packed = true];
|
||||
repeated double rep_double = 33 [packed = true];
|
||||
|
||||
repeated string rep_string = 34;
|
||||
repeated bytes rep_bytes = 35;
|
||||
repeated SubMessage rep_submsg = 36;
|
||||
repeated MyEnum rep_enum = 37 [packed = true];
|
||||
repeated EmptyMessage rep_emptymsg = 38;
|
||||
repeated bytes rep_fbytes = 39;
|
||||
repeated int32 rep_farray = 40 [packed = true];
|
||||
|
||||
optional int32 opt_int32 = 41 [default = 4041];
|
||||
optional int64 opt_int64 = 42 [default = 4042];
|
||||
optional uint32 opt_uint32 = 43 [default = 4043];
|
||||
optional uint64 opt_uint64 = 44 [default = 4044];
|
||||
optional sint32 opt_sint32 = 45 [default = 4045];
|
||||
optional sint64 opt_sint64 = 46 [default = 4046];
|
||||
optional bool opt_bool = 47 [default = false];
|
||||
|
||||
optional fixed32 opt_fixed32 = 48 [default = 4048];
|
||||
optional sfixed32 opt_sfixed32= 49 [default = 4049];
|
||||
optional float opt_float = 50 [default = 4050];
|
||||
|
||||
optional fixed64 opt_fixed64 = 51 [default = 4051];
|
||||
optional sfixed64 opt_sfixed64= 52 [default = 4052];
|
||||
optional double opt_double = 53 [default = 4053];
|
||||
|
||||
optional string opt_string = 54 [default = "4054"];
|
||||
optional bytes opt_bytes = 55 [default = "\x34\x5C\x00\xff"];
|
||||
optional SubMessage opt_submsg = 56;
|
||||
optional MyEnum opt_enum = 57 [default = Second];
|
||||
optional EmptyMessage opt_emptymsg = 58;
|
||||
optional bytes opt_fbytes = 59 [default = "4059"];
|
||||
|
||||
oneof oneof
|
||||
{
|
||||
SubMessage oneof_msg1 = 60;
|
||||
EmptyMessage oneof_msg2 = 61;
|
||||
SubMessage static_msg = 63;
|
||||
}
|
||||
|
||||
optional NonZeroBasedEnum opt_non_zero_based_enum = 62;
|
||||
|
||||
// Second fixed length array field to test the length check logic.
|
||||
repeated fixed32 rep_farray2 = 95 [packed = true];
|
||||
|
||||
// Check support for custom integer sizes
|
||||
required IntSizes req_intsizes = 96;
|
||||
|
||||
// Check support for 8-word descriptors
|
||||
required DescriptorSize8 req_ds8 = 97;
|
||||
|
||||
// Check that extreme integer values are handled correctly
|
||||
// Also checks support for 4-word descriptors
|
||||
required Limits req_limits = 98;
|
||||
|
||||
// Just to make sure that the size of the fields has been calculated
|
||||
// properly, i.e. otherwise a bug in last field might not be detected.
|
||||
required int32 end = 999;
|
||||
|
||||
|
||||
extensions 200 to 255;
|
||||
}
|
||||
|
||||
message TestExtension {
|
||||
extend AllTypes {
|
||||
optional TestExtension testextension = 250;
|
||||
}
|
||||
optional string strval = 1;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue