pax_global_header 0000666 0000000 0000000 00000000064 15245442746 0014527 g ustar 00root root 0000000 0000000 52 comment=3fdf723dca5efe077e7e2ef0f3d33f791af0e511
asn1tools-0.169.0/ 0000775 0000000 0000000 00000000000 15245442746 0013627 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/.coveragerc 0000664 0000000 0000000 00000000033 15245442746 0015744 0 ustar 00root root 0000000 0000000 [run]
relative_files = True asn1tools-0.169.0/.github/ 0000775 0000000 0000000 00000000000 15245442746 0015167 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/.github/FUNDING.yml 0000664 0000000 0000000 00000000020 15245442746 0016774 0 ustar 00root root 0000000 0000000 github: eerimoq
asn1tools-0.169.0/.github/workflows/ 0000775 0000000 0000000 00000000000 15245442746 0017224 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/.github/workflows/python-package.yml 0000664 0000000 0000000 00000005510 15245442746 0022662 0 ustar 00root root 0000000 0000000 name: Python package
on: [push, pull_request]
jobs:
test-python:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.14
uses: actions/setup-python@v5
with:
python-version: '3.14'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install coveralls
- name: Test
run: |
coverage run --source=asn1tools -m unittest discover -t . -s tests
- name: Coveralls
uses: AndreMiras/coveralls-python-action@develop
test-python-sdist:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.14
uses: actions/setup-python@v5
with:
python-version: '3.14'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Test
run: |
make test-sdist
test-c:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.14
uses: actions/setup-python@v5
with:
python-version: '3.14'
- name: Install dependencies
run: |
sudo apt-get install -qq valgrind -y
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Test
run: |
make test-c
make -C examples/benchmarks/c_source
(cd tests && bash <(curl -s https://codecov.io/bash) -X coveragepy)
examples:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.14
uses: actions/setup-python@v5
with:
python-version: '3.14'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Test
run: |
env PYTHONPATH=. python examples/benchmarks/codecs.py
env PYTHONPATH=. python examples/hello_world.py
env PYTHONPATH=. python examples/x509_pem.py
env PYTHONPATH=. python examples/compact_extensions_uper/main.py
env PYTHONPATH=. python examples/programming_types/main.py
release:
needs: [test-python, test-python-sdist, test-c, examples]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags')
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.14
uses: actions/setup-python@v5
with:
python-version: '3.14'
- name: Install pypa/build
run: |
python -m pip install build --user
- name: Build a binary wheel and a source tarball
run: |
git clean -dfx
python -m build --outdir dist/ .
- name: Publish distribution 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
skip_existing: true
password: ${{ secrets.pypi_password }}
asn1tools-0.169.0/.gitignore 0000664 0000000 0000000 00000001571 15245442746 0015623 0 ustar 00root root 0000000 0000000 # Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
test_command_line_*
test_cache
compile_methods_cache
/*.[hc]
/main_*
/massif.*
v0.9.28.tar.gz
asn1c-0.9.28/
main
main*.massif
*.gcno
*.gcda
gmon.out
/*.mk
Cargo.lock
/rust_source.rs
/*.o asn1tools-0.169.0/LICENSE 0000664 0000000 0000000 00000002075 15245442746 0014640 0 ustar 00root root 0000000 0000000 The MIT License (MIT)
Copyright (c) 2017-2019 Erik Moqvist
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.
asn1tools-0.169.0/MANIFEST.in 0000664 0000000 0000000 00000000226 15245442746 0015365 0 ustar 00root root 0000000 0000000 include LICENSE
include Makefile
include examples/programming_types/programming_types.asn
recursive-include tests *.py *.asn *.h *.c *.mk *.rs *.toml
asn1tools-0.169.0/Makefile 0000664 0000000 0000000 00000013052 15245442746 0015270 0 ustar 00root root 0000000 0000000 ifeq ($(origin CC), default)
CC = gcc
endif
C_SOURCES := \
tests/files/c_source/oer.c \
tests/files/c_source/uper.c
FUZZER_CC ?= clang
FUZZER_OER_EXE = main_oer_fuzzer
FUZZER_UPER_EXE = main_uper_fuzzer
FUZZER_OER_C_SOURCES = \
tests/main_oer_fuzzer.c \
tests/files/c_source/oer.c
FUZZER_UPER_C_SOURCES = \
tests/main_uper_fuzzer.c \
tests/files/c_source/uper.c
FUZZER_CFLAGS = \
-fprofile-instr-generate \
-fcoverage-mapping \
-Itests/files/c_source \
-g -fsanitize=address,fuzzer \
-fsanitize=signed-integer-overflow \
-fno-sanitize-recover=all
FUZZER_EXECUTION_TIME ?= 30
CFLAGS := \
-Wall \
-Wextra \
-Wdouble-promotion \
-Wfloat-equal \
-Wformat=2 \
-Wshadow \
-Werror
CFLAGS_EXTRA := \
-Wduplicated-branches \
-Wduplicated-cond \
-Wjump-misses-init \
-Wlogical-op \
-Wnull-dereference \
-Wrestrict \
-Wconversion \
-Wpedantic
CFLAGS_EXTRA_CLANG := \
-fsanitize=address \
-fsanitize=undefined,nullability \
-Warray-bounds-pointer-arithmetic \
-Wassign-enum \
-Wcast-align \
-Wcast-qual \
-Wchar-subscripts \
-Wcomma \
-Wcomment \
-Wconditional-uninitialized \
-Wdate-time \
-Wdocumentation \
-Wduplicate-decl-specifier \
-Wduplicate-enum \
-Wduplicate-method-arg \
-Wduplicate-method-match \
-Wembedded-directive \
-Wempty-translation-unit \
-Wexpansion-to-defined \
-Wflexible-array-extensions \
-Wfloat-conversion \
-Wfloat-equal \
-Wfloat-overflow-conversion \
-Wfloat-zero-conversion \
-Wformat-non-iso \
-Wformat-nonliteral \
-Wformat-pedantic \
-Wfour-char-constants \
-Wgnu-anonymous-struct \
-Wgnu-array-member-paren-init \
-Wgnu-auto-type \
-Wgnu-binary-literal \
-Wgnu-case-range \
-Wgnu-complex-integer \
-Wgnu-compound-literal-initializer \
-Wgnu-conditional-omitted-operand \
-Wgnu-designator \
-Wgnu-empty-initializer \
-Wgnu-empty-struct \
-Wgnu-flexible-array-initializer \
-Wgnu-flexible-array-union-member \
-Wgnu-folding-constant \
-Wgnu-imaginary-constant \
-Wgnu-include-next \
-Wgnu-label-as-value \
-Wgnu-redeclared-enum \
-Wgnu-statement-expression \
-Wgnu-union-cast \
-Wgnu-zero-line-directive \
-Wgnu-zero-variadic-macro-arguments \
-Wheader-hygiene \
-Widiomatic-parentheses \
-Wimplicit \
-Wimplicit-fallthrough \
-Wloop-analysis \
-Wmethod-signatures \
-Wmissing-braces \
-Wmissing-field-initializers \
-Wnested-anon-types \
-Wnewline-eof \
-Wnull-pointer-arithmetic \
-Woverlength-strings \
-Wpointer-arith \
-Wsign-compare \
-Wtautological-compare \
-Wundef \
-Wuninitialized \
-Wunreachable-code \
-Wunreachable-code-aggressive \
-Wunused-comparison \
-Wunused-const-variable \
-Wunused-parameter \
-Wunused-variable \
-Wvariadic-macros \
-Wzero-as-null-pointer-constant \
-Wzero-length-array
.PHONY: test
test:
python3 -m unittest discover -t . -s tests
$(MAKE) test-sdist
env PYTHONPATH=. python3 examples/benchmarks/packages/ber.py
env PYTHONPATH=. python3 examples/benchmarks/packages/uper.py
env PYTHONPATH=. python3 examples/benchmarks/codecs.py
env PYTHONPATH=. python3 examples/benchmarks/compile_methods.py
env PYTHONPATH=. python3 examples/benchmarks/question/question.py
env PYTHONPATH=. python3 examples/hello_world.py
env PYTHONPATH=. python3 examples/x509_pem.py
env PYTHONPATH=. python3 examples/compact_extensions_uper/main.py
env PYTHONPATH=. python3 examples/programming_types/main.py
$(MAKE) test-c
env FUZZER_EXECUTION_TIME=1 $(MAKE) test-c-fuzzer
$(MAKE) -C examples/benchmarks/c_source
python3 -m pycodestyle $$(git ls-files "asn1tools/*.py")
.PHONY: codespell
codespell:
codespell -d $$(git ls-files | grep -v ietf \
| grep -v 3gpp \
| grep -v generated \
| grep -v "\\.rs" \
| grep -v asn1tools/source/rust \
| grep -v "\.asn")
.PHONY: test-c
test-c:
for f in $(C_SOURCES) ; do \
$(CC) $(CFLAGS) $(CFLAGS_EXTRA) -std=c99 -O3 -c $$f ; \
clang $(CFLAGS) $(CFLAGS_EXTRA_CLANG) -std=c99 -O3 -c $$f ; \
done
$(MAKE) -C tests
.PHONY: test-c-oer-fuzzer-run
test-c-oer-fuzzer-run:
$(FUZZER_CC) $(FUZZER_CFLAGS) $(FUZZER_OER_C_SOURCES) -o $(FUZZER_OER_EXE)
rm -f $(FUZZER_OER_EXE).profraw
LLVM_PROFILE_FILE="$(FUZZER_OER_EXE).profraw" \
./$(FUZZER_OER_EXE) \
-max_total_time=$(FUZZER_EXECUTION_TIME) \
-print_final_stats
llvm-profdata merge \
-sparse $(FUZZER_OER_EXE).profraw \
-o $(FUZZER_OER_EXE).profdata
llvm-cov show ./$(FUZZER_OER_EXE) \
-instr-profile=$(FUZZER_OER_EXE).profdata
.PHONY: test-c-uper-fuzzer-run
test-c-uper-fuzzer-run:
$(FUZZER_CC) $(FUZZER_CFLAGS) $(FUZZER_UPER_C_SOURCES) -o $(FUZZER_UPER_EXE)
rm -f $(FUZZER_UPER_EXE).profraw
LLVM_PROFILE_FILE="$(FUZZER_UPER_EXE).profraw" \
./$(FUZZER_UPER_EXE) \
-max_total_time=$(FUZZER_EXECUTION_TIME) \
-print_final_stats
llvm-profdata merge \
-sparse $(FUZZER_UPER_EXE).profraw \
-o $(FUZZER_UPER_EXE).profdata
llvm-cov show ./$(FUZZER_UPER_EXE) \
-instr-profile=$(FUZZER_UPER_EXE).profdata
.PHONY: test-c-fuzzer
test-c-fuzzer:
$(MAKE) test-c-oer-fuzzer-run
$(MAKE) test-c-uper-fuzzer-run
echo
echo "REPORT:"
echo
llvm-cov report ./$(FUZZER_OER_EXE) \
-instr-profile=$(FUZZER_OER_EXE).profdata
echo
llvm-cov report ./$(FUZZER_UPER_EXE) \
-instr-profile=$(FUZZER_UPER_EXE).profdata
.PHONY: test-rust
test-rust:
cd tests/rust_source && cargo run
.PHONY: test-sdist
test-sdist:
rm -rf dist
python3 setup.py sdist
cd dist && \
mkdir test && \
cd test && \
tar xf ../*.tar.gz && \
cd asn1tools-* && \
python3 -m unittest discover -t . -s tests
.PHONY: release-to-pypi
release-to-pypi:
python3 setup.py sdist
python3 setup.py bdist_wheel --universal
twine upload dist/*
asn1tools-0.169.0/README.rst 0000664 0000000 0000000 00000027764 15245442746 0015336 0 ustar 00root root 0000000 0000000 |coverage|_
|codecov|_
|nala|_
About
=====
A Python package for `ASN.1`_ parsing, encoding and decoding.
This project is *under development* and does only support a subset
of the ASN.1 specification syntax.
Supported codecs:
- Basic Encoding Rules (BER)
- Distinguished Encoding Rules (DER)
- Generic String Encoding Rules (GSER)
- JSON Encoding Rules (JER)
- Basic Octet Encoding Rules (OER)
- Aligned Packed Encoding Rules (PER)
- Unaligned Packed Encoding Rules (UPER)
- XML Encoding Rules (XER)
Miscellaneous features:
- `C` source code generator for OER and UPER (with some limitations).
Project homepage: https://github.com/eerimoq/asn1tools
Documentation: http://asn1tools.readthedocs.org/en/latest
Known limitations
=================
- The ``CLASS`` keyword (X.681) and its friends are not yet supported.
- Parametrization (X.683) is not yet supported.
- The ``EMBEDDED PDV`` type is not yet supported.
- The ``ANY`` and ``ANY DEFINED BY`` types are not supported. They
were removed from the ASN.1 standard 1994.
- ``WITH COMPONENT`` and ``WITH COMPONENTS`` constraints are ignored,
except for OER ``REAL``.
- The ``DURATION`` type is not yet supported.
Installation
============
.. code-block:: python
pip install asn1tools
Example Usage
=============
This is an example ASN.1 specification defining the messages of a
fictitious Foo protocol (based on the FooProtocol on Wikipedia).
.. code-block:: text
Foo DEFINITIONS ::= BEGIN
Question ::= SEQUENCE {
id INTEGER,
question IA5String
}
Answer ::= SEQUENCE {
id INTEGER,
answer BOOLEAN
}
END
Scripting
---------
`Compile`_ the ASN.1 specification, and `encode`_ and `decode`_ a
question using the default codec (BER).
.. code-block:: python
>>> import asn1tools
>>> foo = asn1tools.compile_files('tests/files/foo.asn')
>>> encoded = foo.encode('Question', {'id': 1, 'question': 'Is 1+1=3?'})
>>> encoded
bytearray(b'0\x0e\x02\x01\x01\x16\x09Is 1+1=3?')
>>> foo.decode('Question', encoded)
{'id': 1, 'question': 'Is 1+1=3?'}
The same ASN.1 specification, but using the PER codec.
.. code-block:: python
>>> import asn1tools
>>> foo = asn1tools.compile_files('tests/files/foo.asn', 'per')
>>> encoded = foo.encode('Question', {'id': 1, 'question': 'Is 1+1=3?'})
>>> encoded
bytearray(b'\x01\x01\tIs 1+1=3?')
>>> foo.decode('Question', encoded)
{'id': 1, 'question': 'Is 1+1=3?'}
See the `examples`_ folder for additional examples.
Command line tool
-----------------
The shell subcommand
^^^^^^^^^^^^^^^^^^^^
Use the command line shell to convert data between given formats. The
default input codec is BER and output codec is GSER (produces human
readable text).
.. code-block:: text
> asn1tools shell
Welcome to the asn1tools shell!
$ help
Commands:
compile
convert
exit
help
$ compile tests/files/foo.asn
$ convert Question 300e0201011609497320312b313d333f
question Question ::= {
id 1,
question "Is 1+1=3?"
}
$ compile --output-codec xer tests/files/foo.asn
$ convert Question 300e0201011609497320312b313d333f
1
Is 1+1=3?
$ compile -o uper tests/files/foo.asn
$ convert Question 300e0201011609497320312b313d333f
01010993cd03156c5eb37e
$ exit
>
The convert subcommand
^^^^^^^^^^^^^^^^^^^^^^
Convert given encoded Question from BER to GSER (produces human
readable text).
.. code-block:: text
> asn1tools convert tests/files/foo.asn Question 300e0201011609497320312b313d333f
question Question ::= {
id 1,
question "Is 1+1=3?"
}
>
Convert given encoded Question from UPER to XER (xml).
.. code-block:: text
> asn1tools convert -i uper -o xer tests/files/foo.asn Question 01010993cd03156c5eb37e
1
Is 1+1=3?
>
Convert given encoded Question from UPER to JER (json).
.. code-block:: text
> asn1tools convert -i uper -o jer tests/files/foo.asn Question 01010993cd03156c5eb37e
{
"id": 1,
"question": "Is 1+1=3?"
}
>
Continuously convert encoded Questions read from standard input. Any
line that cannot be converted is printed as is, in this example the
dates.
.. code-block:: text
> cat encoded.txt
2018-02-24 11:22:09
300e0201011609497320312b313d333f
2018-02-24 11:24:15
300e0201021609497320322b323d353f
> cat encoded.txt | asn1tools convert tests/files/foo.asn Question -
2018-02-24 11:22:09
question Question ::= {
id 1,
question "Is 1+1=3?"
}
2018-02-24 11:24:15
question Question ::= {
id 2,
question "Is 2+2=5?"
}
>
The convert subcommand with a cache
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Convert given encoded PCCH-Message from UPER to GSER with the
``--cache-dir`` option set to ``my_cache``. Using a cache
significantly reduces the command execution time after the first call.
.. code-block:: text
> time asn1tools convert --cache-dir my_cache -i uper tests/files/3gpp/rrc_8_6_0.asn PCCH-Message 28
pcch-message PCCH-Message ::= {
message c1 : paging : {
systemInfoModification true,
nonCriticalExtension {
}
}
}
real 0m2.090s
user 0m1.977s
sys 0m0.032s
> time asn1tools convert --cache-dir my_cache -i uper tests/files/3gpp/rrc_8_6_0.asn PCCH-Message 28
pcch-message PCCH-Message ::= {
message c1 : paging : {
systemInfoModification true,
nonCriticalExtension {
}
}
}
real 0m0.276s
user 0m0.197s
sys 0m0.026s
>
The parse subcommand
^^^^^^^^^^^^^^^^^^^^
Parse given ASN.1 specification and write it as a Python dictionary to
given file. Use the created file to convert given encoded Question
from BER to GSER (produces human readable text). The conversion is
significantly faster than passing .asn-file(s) to the convert
subcommand, especially for larger ASN.1 specifications.
.. code-block:: text
> asn1tools parse tests/files/foo.asn foo.py
> asn1tools convert foo.py Question 300e0201011609497320312b313d333f
question Question ::= {
id 1,
question "Is 1+1=3?"
}
>
The generate C source subcommand
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Generate OER or UPER C source code from an ASN.1 specification.
No dynamic memory is used in the generated code. To achieve this all
types in the ASN.1 specification must have a known maximum size,
i.e. ``INTEGER (0..7)``, ``OCTET STRING (SIZE(12))``, etc.
Below is an example generating OER C source code from
`tests/files/c_source/c_source.asn`_.
.. code-block:: text
> asn1tools generate_c_source --namespace oer tests/files/c_source/c_source.asn
Successfully generated oer.h and oer.c.
The same as above, but generate UPER C source code instead of OER.
.. code-block:: text
> asn1tools generate_c_source --codec uper --namespace uper tests/files/c_source/c_source.asn
Successfully generated uper.h and uper.c.
The same as the first example, but also generate fuzz testing C source
code for `libFuzzer`_.
.. code-block:: text
> asn1tools generate_c_source --namespace oer --generate-fuzzer tests/files/c_source/c_source.asn
Successfully generated oer.h and oer.c.
Successfully generated oer_fuzzer.c and oer_fuzzer.mk.
Run "make -f oer_fuzzer.mk" to build and run the fuzzer. Requires a
recent version of clang.
See `oer.h`_, `oer.c`_, `uper.h`_, `uper.c`_, `oer_fuzzer.c`_ and
`oer_fuzzer.mk`_ for the contents of the generated files.
Limitations by design:
- Only the types ``BOOLEAN``, ``INTEGER``, ``NULL``, ``OCTET STRING``,
``BIT STRING``, ``ENUMERATED``, ``SEQUENCE``, ``SEQUENCE OF``, and ``CHOICE``
are supported. The OER generator also supports ``REAL``.
- All types must have a known maximum size, i.e. ``INTEGER (0..7)``,
``OCTET STRING (SIZE(12))``.
- ``INTEGER`` must be 64 bits or less.
- ``REAL`` must be IEEE 754 binary32 or binary64. binary32 is
generated as ``float`` and binary64 as ``double``.
- Recursive types are not supported.
Known limitations:
- Extension additions (``...``) are only supported in the OER generator.
See `compact_extensions_uper`_ for how to make UPER ``CHOICE`` and
``SEQUENCE`` extendable without using ``...``.
- Named numbers in ``ENUMERATED`` are not yet supported.
Other OER and/or UPER C code generators:
- https://github.com/vlm/asn1c
- https://github.com/ttsiodras/asn1scc
See the `benchmark example`_ for a comparison of `asn1c`, `asn1scc`
and `asn1tools`.
Contributing
============
#. Fork the repository.
#. Install prerequisites.
.. code-block:: text
pip install -r requirements.txt
#. Implement the new feature or bug fix.
#. Implement test case(s) to ensure that future changes do not break
legacy.
#. Run the tests.
.. code-block:: text
make test
#. Create a pull request.
Specifications
==============
ASN.1 specifications released by ITU and IETF.
General
-------
- `X.680: Specification of basic notation
`_
- `X.681: Information object specification
`_
- `X.682: Constraint specification
`_
- `X.683: Parameterization of ASN.1 specifications
`_
Encodings
---------
- `X.690: Specification of Basic Encoding Rules (BER), Canonical
Encoding Rules (CER) and Distinguished Encoding Rules (DER)
`_
- `X.691: Specification of Packed Encoding Rules (PER)
`_
- `X.693: XML Encoding Rules (XER)
`_
- `X.696: Specification of Octet Encoding Rules (OER)
`_
- `RFC 3641: Generic String Encoding Rules (GSER) for ASN.1
`_
- `Overview of the JSON Encoding Rules (JER)
`_
.. |coverage| image:: https://coveralls.io/repos/github/eerimoq/asn1tools/badge.svg?branch=master
.. _coverage: https://coveralls.io/github/eerimoq/asn1tools
.. |codecov| image:: https://codecov.io/gh/eerimoq/asn1tools/branch/master/graph/badge.svg
.. _codecov: https://codecov.io/gh/eerimoq/asn1tools
.. |nala| image:: https://img.shields.io/badge/nala-test-blue.svg
.. _nala: https://github.com/eerimoq/nala
.. _ASN.1: https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One
.. _Compile: http://asn1tools.readthedocs.io/en/latest/#asn1tools.compile_files
.. _encode: http://asn1tools.readthedocs.io/en/latest/#asn1tools.compiler.Specification.encode
.. _decode: http://asn1tools.readthedocs.io/en/latest/#asn1tools.compiler.Specification.decode
.. _examples: https://github.com/eerimoq/asn1tools/tree/master/examples
.. _tests/files/c_source/c_source.asn: https://github.com/eerimoq/asn1tools/blob/master/tests/files/c_source/c_source.asn
.. _oer.h: https://github.com/eerimoq/asn1tools/blob/master/tests/files/c_source/oer.h
.. _oer.c: https://github.com/eerimoq/asn1tools/blob/master/tests/files/c_source/oer.c
.. _uper.h: https://github.com/eerimoq/asn1tools/blob/master/tests/files/c_source/uper.h
.. _uper.c: https://github.com/eerimoq/asn1tools/blob/master/tests/files/c_source/uper.c
.. _oer_fuzzer.c: https://github.com/eerimoq/asn1tools/blob/master/tests/files/c_source/oer_fuzzer.c
.. _oer_fuzzer.mk: https://github.com/eerimoq/asn1tools/blob/master/tests/files/c_source/oer_fuzzer.mk
.. _libFuzzer: https://llvm.org/docs/LibFuzzer.html
.. _benchmark example: https://github.com/eerimoq/asn1tools/blob/master/examples/benchmarks/c_source
.. _compact_extensions_uper: https://github.com/eerimoq/asn1tools/blob/master/examples/compact_extensions_uper
asn1tools-0.169.0/asn1tools/ 0000775 0000000 0000000 00000000000 15245442746 0015552 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/asn1tools/__init__.py 0000664 0000000 0000000 00000035241 15245442746 0017670 0 ustar 00root root 0000000 0000000 """The top level of the ASN.1 tools package contains commonly used
functions and classes, and the command line interface.
"""
import sys
import os
import argparse
import binascii
import logging
from pprint import pformat
try:
from prompt_toolkit.completion import WordCompleter
from prompt_toolkit import PromptSession
from prompt_toolkit.history import FileHistory
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
has_prompt_toolkit = True
except ImportError:
has_prompt_toolkit = False
from .compiler import compile_dict
from .compiler import compile_string
from .compiler import compile_files
from .compiler import pre_process_dict
from .parser import parse_string
from .parser import parse_files
from .parser import ParseError
from .errors import Error
from .errors import EncodeError
from .errors import DecodeError
from .errors import CompileError
from .errors import ConstraintsError
from . source import c
from . source import rust
from .version import __version__
__author__ = 'Erik Moqvist'
class ArgumentParserError(Error):
pass
class ArgumentParser(argparse.ArgumentParser):
def exit(self, status=0, message=None):
if message:
self._print_message(message, sys.stdout)
raise ArgumentParserError(message)
def error(self, message):
self.print_usage(sys.stdout)
message = '{}: error: {}'.format(self.prog, message)
print(message)
raise ArgumentParserError(message)
def _import_module(pyfilepath):
module_name = os.path.splitext(os.path.basename(pyfilepath))[0]
if sys.version_info > (3, 4):
import importlib.util
spec = importlib.util.spec_from_file_location(module_name, pyfilepath)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
else:
import imp
module = imp.load_source(module_name, pyfilepath)
return module
def _convert_hexstring(input_spec,
output_spec,
output_codec,
type_name,
hexstring):
try:
encoded = binascii.unhexlify(hexstring)
except Exception as e:
raise TypeError("'{}': {}".format(hexstring, str(e)))
decoded = input_spec.decode(type_name, encoded)
if output_codec in ['gser', 'xer', 'jer']:
decoded = output_spec.encode(type_name, decoded, indent=4).strip()
else:
decoded = binascii.hexlify(output_spec.encode(type_name, decoded))
print(decoded.decode('latin-1'))
def _compile_files(specs, input_codec, output_codec, cache_dir):
py_count = [spec.endswith('.py') for spec in specs].count(True)
if py_count > 0:
if py_count != 1:
raise Exception('Expected one .py-file, but got {}.'.format(py_count))
module = _import_module(specs[0])
parsed = module.SPECIFICATION
input_spec = compile_dict(parsed, input_codec)
output_spec = compile_dict(parsed, output_codec)
else:
input_spec = compile_files(specs,
input_codec,
cache_dir=cache_dir)
output_spec = compile_files(specs,
output_codec,
cache_dir=cache_dir)
return input_spec, output_spec
def _do_convert(args):
input_spec, output_spec = _compile_files(args.specification,
args.input_codec,
args.output_codec,
args.cache_dir)
if args.hexstring == '-':
for hexstring in sys.stdin:
hexstring = hexstring.strip('\r\n')
if hexstring:
try:
_convert_hexstring(input_spec,
output_spec,
args.output_codec,
args.type,
hexstring)
except TypeError:
print(hexstring)
except DecodeError as e:
print(hexstring)
print(str(e))
else:
print(hexstring)
else:
_convert_hexstring(input_spec,
output_spec,
args.output_codec,
args.type,
args.hexstring)
def _handle_command_compile(line):
parser = ArgumentParser(prog='compile')
parser.add_argument('-i', '--input-codec',
choices=('ber', 'der', 'jer', 'oer', 'per', 'uper', 'xer'),
default='ber',
help='Input codec (default: %(default)s).')
parser.add_argument('-o', '--output-codec',
choices=(
'ber', 'der', 'jer', 'oer', 'per', 'uper', 'xer', 'gser'
),
default='gser',
help='Output codec (default: %(default)s).')
parser.add_argument('-c', '--cache-dir',
help='Cache directory.')
parser.add_argument('specification',
nargs='+',
help='ASN.1 specification as one or more .asn files.')
try:
args = parser.parse_args(args=line.split()[1:])
except ArgumentParserError:
return None, None, None
try:
input_spec, output_spec = _compile_files(args.specification,
args.input_codec,
args.output_codec,
args.cache_dir)
return input_spec, output_spec, args.output_codec
except Exception as e:
print('error: {}'.format(str(e)))
return None, None, None
def _handle_command_convert(line, input_spec, output_spec, output_codec):
if not input_spec:
print("No compiled specification found. Please use the "
"'compile' command to compile one.")
return
parser = ArgumentParser(prog='convert')
parser.add_argument('type', help='Type to convert.')
parser.add_argument(
'hexstring',
help='Hexstring to convert.')
try:
args = parser.parse_args(args=line.split()[1:])
except ArgumentParserError:
return
try:
_convert_hexstring(input_spec,
output_spec,
output_codec,
args.type,
args.hexstring)
except Exception as e:
print('error: {}'.format(str(e)))
def _handle_command_help():
print('Commands:')
print(' compile')
print(' convert')
print(' exit')
print(' help')
def _do_shell(_args):
if not has_prompt_toolkit:
raise RuntimeError(
'Shell needs prompt_toolkit, but the package is not installed')
commands = ['compile', 'convert', 'help', 'exit']
completer = WordCompleter(commands, WORD=True)
user_home = os.path.expanduser('~')
history = FileHistory(os.path.join(user_home, '.asn1tools-history.txt'))
session = PromptSession(completer=completer,
complete_while_typing=True,
auto_suggest=AutoSuggestFromHistory(),
enable_history_search=True,
history=history)
input_spec = None
output_spec = None
output_codec = None
print("\nWelcome to the asn1tools shell!\n")
while True:
try:
line = session.prompt(u'$ ')
except EOFError:
return
line = line.strip()
if line:
if line.startswith('compile'):
input_spec, output_spec, output_codec = _handle_command_compile(line)
elif line.startswith('convert'):
_handle_command_convert(line,
input_spec,
output_spec,
output_codec)
elif line == 'help':
_handle_command_help()
elif line == 'exit':
return
else:
print('{}: command not found'.format(line))
def _do_parse(args):
parsed = parse_files(args.specification)
with open(args.outfile, 'w') as fout:
fout.write('SPECIFICATION = {}'.format(pformat(parsed)))
def _do_generate_c_source(args):
if args.namespace is None:
name = os.path.basename(args.specification[0])
name = os.path.splitext(name)[0]
else:
name = args.namespace
filename_h = name + '.h'
filename_c = name + '.c'
fuzzer_filename_c = name + '_fuzzer.c'
fuzzer_filename_mk = name + '_fuzzer.mk'
compiled = compile_files(args.specification,
args.codec)
header, source, fuzzer_source, fuzzer_makefile = c.generate(
compiled,
args.codec,
name,
filename_h,
filename_c,
fuzzer_filename_c)
with open(filename_h, 'w') as fout:
fout.write(header)
with open(filename_c, 'w') as fout:
fout.write(source)
print('Successfully generated {} and {}.'.format(filename_h,
filename_c))
if args.generate_fuzzer:
with open(fuzzer_filename_c, 'w') as fout:
fout.write(fuzzer_source)
with open(fuzzer_filename_mk, 'w') as fout:
fout.write(fuzzer_makefile)
print('Successfully generated {} and {}.'.format(fuzzer_filename_c,
fuzzer_filename_mk))
print()
print(
'Run "make -f {}" to build and run the fuzzer. Requires a'.format(
fuzzer_filename_mk))
print('recent version of clang.')
def _do_generate_rust_source(args):
name = os.path.basename(args.specification[0])
name = os.path.splitext(name)[0]
filename_rs = name + '.rs'
compiled = compile_files(args.specification,
args.codec)
source = rust.generate(compiled, args.codec)
with open(filename_rs, 'w') as fout:
fout.write(source)
print('Successfully generated {}.'.format(filename_rs))
def _main():
parser = argparse.ArgumentParser(
description='Various ASN.1 utilities.')
parser.add_argument('-d', '--debug', action='store_true')
parser.add_argument('-v', '--verbose',
choices=(0, 1, 2),
type=int,
default=1,
help=('Control the verbosity; disable(0), warning(1) '
'and debug(2) (default: %(default)s).'))
parser.add_argument('--version',
action='version',
version=__version__,
help='Print version information and exit.')
# Workaround to make the subparser required in Python 3.
subparsers = parser.add_subparsers(title='subcommands',
dest='subcommand')
subparsers.required = True
# The 'convert' subparser.
subparser = subparsers.add_parser(
'convert',
description='Convert given hextring and print it to standard output.')
subparser.add_argument(
'-i', '--input-codec',
choices=('ber', 'der', 'jer', 'oer', 'per', 'uper', 'xer'),
default='ber',
help='Input format (default: %(default)s).')
subparser.add_argument(
'-o', '--output-codec',
choices=('ber', 'der', 'jer', 'oer', 'per', 'uper', 'xer', 'gser'),
default='gser',
help='Output format (default: %(default)s).')
subparser.add_argument('-c', '--cache-dir',
help='Cache directory.')
subparser.add_argument(
'specification',
nargs='+',
help=('ASN.1 specification as one or more .asn files or one .py '
'file. The .py-file may be created with the parse subcommand.'))
subparser.add_argument('type', help='Type to convert.')
subparser.add_argument(
'hexstring',
help='Hexstring to convert, or - to read hexstrings from standard input.')
subparser.set_defaults(func=_do_convert)
# The 'shell' subparser.
subparser = subparsers.add_parser('shell',
description='An interactive shell.')
subparser.set_defaults(func=_do_shell)
# The 'parse' subparser.
subparser = subparsers.add_parser('parse',
description='Convert to a Python dictionary.')
subparser.add_argument('specification',
nargs='+',
help='ASN.1 specification as one or more .asn files.')
subparser.add_argument('outfile',
help='Output file name.')
subparser.set_defaults(func=_do_parse)
# The 'generate_c_source' subparser.
subparser = subparsers.add_parser(
'generate_c_source',
description='Generate C source code from given ASN.1 specification.')
subparser.add_argument(
'-c', '--codec',
choices=('oer', 'uper'),
default='oer',
help='Codec to generate code for (default: %(default)s).')
subparser.add_argument(
'-n', '--namespace',
help='Namespace of defines, structs, functions, files, etc.')
subparser.add_argument(
'-f', '--generate-fuzzer',
action='store_true',
help='Also generate fuzzer source code.')
subparser.add_argument('specification',
nargs='+',
help='ASN.1 specification as one or more .asn files.')
subparser.set_defaults(func=_do_generate_c_source)
# The 'generate_rust_source' subparser.
subparser = subparsers.add_parser(
'generate_rust_source',
description='Generate Rust source code from given ASN.1 specification.')
subparser.add_argument(
'-c', '--codec',
choices=('uper', ),
default='uper',
help='Codec to generate code for (default: %(default)s).')
subparser.add_argument('specification',
nargs='+',
help='ASN.1 specification as one or more .asn files.')
subparser.set_defaults(func=_do_generate_rust_source)
args = parser.parse_args()
levels = [logging.CRITICAL, logging.WARNING, logging.DEBUG]
level = levels[args.verbose]
logging.basicConfig(format='%(levelname)s: %(message)s',
level=level)
if args.debug:
args.func(args)
else:
try:
args.func(args)
except BaseException as e:
sys.exit('error: {}'.format(str(e)))
asn1tools-0.169.0/asn1tools/__main__.py 0000664 0000000 0000000 00000000044 15245442746 0017642 0 ustar 00root root 0000000 0000000 from . import _main as main
main()
asn1tools-0.169.0/asn1tools/codecs/ 0000775 0000000 0000000 00000000000 15245442746 0017012 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/asn1tools/codecs/__init__.py 0000664 0000000 0000000 00000023772 15245442746 0021136 0 ustar 00root root 0000000 0000000 import binascii
from datetime import datetime
from datetime import timedelta
from functools import wraps
from ..errors import Error
from ..errors import EncodeError as _EncodeError
from ..errors import DecodeError as _DecodeError
from ..errors import ConstraintsError as _ConstraintsError
from .. import compat
class BaseType(object):
"""
Base Type class containing common functionality between all codecs
"""
def __init__(self, name, type_name):
self.name = name
self.type_name = type_name
self.optional = False
self.default = None
def set_default(self, value):
self.default = value
def get_default(self):
return self.default
def has_default(self):
return self.default is not None
def is_default(self, value):
return value == self.default
def encode(self, *args, **kwargs):
raise NotImplementedError('To be implemented by subclasses.')
def decode(self, *args, **kwargs):
raise NotImplementedError('To be implemented by subclasses.')
def __repr__(self):
return '{}({})'.format(self.__class__.__name__,
self.name)
def type_label(self):
return '{}({})'.format(self.type_name, self.name) if self.name else self.type_name
class ErrorWithLocation(Exception):
"""
Mixin for Error classes which have location list
"""
def __init__(self, message, location=None):
"""
:param str message:
:param BaseType location: Type error occured for
"""
self.message = message
self.location = [location] if location else []
def add_location(self, element):
"""
Add location data for element
:param BaseType element:
:return:
"""
# Don't add name if it is blank (for SEQUENCE OF, SET OF etc)
if (not getattr(element, 'no_error_location', False) and
(not self.location or element != self.location[-1])):
self.location.append(element)
@property
def location_str(self):
return '.'.join(loc.name for loc in self.location[::-1] if loc.name)
def __str__(self):
if self.location:
return "{}: {}".format(self.location_str, self.message)
else:
return self.message
class EncodeError(ErrorWithLocation, _EncodeError):
"""General ASN.1 encode error.
"""
pass
class DecodeError(ErrorWithLocation, _DecodeError):
"""
General ASN.1 decode error with error location in the message.
"""
def __init__(self, message, offset=None, location=None):
"""
:param str message: Message for error
:param int offset: Data offset at which error occurred. Can be bits or bytes depending on codec
:param BaseType location: Element in which error occurred
"""
super(DecodeError, self).__init__(message, location=location)
self.offset = offset
def __str__(self):
if self.location:
_str = "{}: {}".format(self.location_str, self.message)
else:
_str = self.message
if self.offset is not None:
_str += self.get_offset_message()
return _str
def get_offset_message(self):
"""
Get offset details to add to error message
:return:
"""
return ' (At offset: {})'.format(self.offset)
class ConstraintsError(ErrorWithLocation, _ConstraintsError):
"""
General ASN.1 constraints error with error location in the message.
"""
pass
class OutOfDataError(DecodeError):
"""
Error for when trying to read data beyond length of type
"""
def __init__(self, offset_bits, location=None):
super(OutOfDataError, self).__init__(
'out of data', offset=offset_bits, location=location)
def get_offset_message(self):
"""
Get offset details to add to error message
:return:
"""
return ' (At bit offset: {})'.format(self.offset)
def _generalized_time_to_datetime(string):
length = len(string)
if '.' in string:
try:
return datetime.strptime(string, '%Y%m%d%H%M.%f')
except ValueError:
return datetime.strptime(string, '%Y%m%d%H%M%S.%f')
elif ',' in string:
try:
return datetime.strptime(string, '%Y%m%d%H%M,%f')
except ValueError:
return datetime.strptime(string, '%Y%m%d%H%M%S,%f')
elif length == 12:
return datetime.strptime(string, '%Y%m%d%H%M')
elif length == 14:
return datetime.strptime(string, '%Y%m%d%H%M%S')
else:
raise ValueError
def format_or(items):
"""Return a string of comma separated items, with the last to items
separated by "or".
[1, 2, 3] -> "1, 2 or 3"
"""
formatted_items = []
for item in items:
try:
item = "'" + item + "'"
except TypeError:
item = str(item)
formatted_items.append(item)
if len(items) == 1:
return formatted_items[0]
else:
return '{} or {}'.format(', '.join(formatted_items[:-1]),
formatted_items[-1])
def utc_time_to_datetime(string):
"""Convert given ASN.1 UTC time string `string` to a
``datetime.datetime`` object.
"""
length = len(string)
try:
if string[-1] == 'Z':
if length == 11:
return datetime.strptime(string[:-1], '%y%m%d%H%M')
elif length == 13:
return datetime.strptime(string[:-1], '%y%m%d%H%M%S')
else:
raise ValueError
elif length == 15:
return compat.strptime(string, '%y%m%d%H%M%z')
elif length == 17:
return compat.strptime(string, '%y%m%d%H%M%S%z')
else:
raise ValueError
except (ValueError, IndexError):
raise Error(
"Expected a UTC time string, but got '{}'.".format(string))
def utc_time_from_datetime(date):
"""Convert given ``datetime.datetime`` object `date` to an ASN.1 UTC
time string.
"""
fmt = '%y%m%d%H%M'
if date.second > 0:
fmt += '%S'
if date.tzinfo is None:
fmt += 'Z'
else:
fmt += '%z'
return date.strftime(fmt)
def restricted_utc_time_to_datetime(string):
"""Convert given restricted ASN.1 UTC time string `string` to a
``datetime.datetime`` object.
"""
try:
if string[-1] != 'Z':
raise ValueError
if len(string) != 13:
raise ValueError
return datetime.strptime(string[:-1], '%y%m%d%H%M%S')
except (ValueError, IndexError):
raise Error(
"Expected a restricted UTC time string, but got '{}'.".format(
string))
def restricted_utc_time_from_datetime(date):
"""Convert given ``datetime.datetime`` object `date` to an restricted
ASN.1 UTC time string.
"""
if date.tzinfo is not None:
date -= date.utcoffset()
return date.strftime('%y%m%d%H%M%S') + 'Z'
def generalized_time_to_datetime(string):
"""Convert given ASN.1 generalized time string `string` to a
``datetime.datetime`` object.
"""
try:
if string[-1] == 'Z':
date = _generalized_time_to_datetime(string[:-1])
return date.replace(tzinfo=compat.timezone(timedelta(hours=0)))
elif string[-5] in '-+':
if '.' in string:
try:
return compat.strptime(string, '%Y%m%d%H%M.%f%z')
except ValueError:
return compat.strptime(string, '%Y%m%d%H%M%S.%f%z')
elif ',' in string:
try:
return compat.strptime(string, '%Y%m%d%H%M,%f%z')
except ValueError:
return compat.strptime(string, '%Y%m%d%H%M%S,%f%z')
else:
return compat.strptime(string, '%Y%m%d%H%M%S%z')
else:
return _generalized_time_to_datetime(string)
except (ValueError, IndexError):
raise Error(
"Expected a generalized time string, but got '{}'.".format(
string))
def generalized_time_from_datetime(date):
"""Convert given ``datetime.datetime`` object `date` to an ASN.1
generalized time string.
"""
if date.second == 0:
if date.microsecond > 0:
string = date.strftime('%Y%m%d%H%M.%f').rstrip('0')
else:
string = date.strftime('%Y%m%d%H%M')
else:
if date.microsecond > 0:
string = date.strftime('%Y%m%d%H%M%S.%f').rstrip('0')
else:
string = date.strftime('%Y%m%d%H%M%S')
if date.tzinfo is not None:
if date.utcoffset():
string += date.strftime('%z')
else:
string += 'Z'
return string
def restricted_generalized_time_to_datetime(string):
"""Convert given restricted ASN.1 generalized time string `string` to
a ``datetime.datetime`` object.
"""
try:
if string[-1] != 'Z':
raise ValueError
if '.' in string:
if string[-2] == '0':
raise ValueError
if string[14] != '.':
raise ValueError
return datetime.strptime(string[:-1], '%Y%m%d%H%M%S.%f')
elif len(string) != 15:
raise ValueError
return datetime.strptime(string[:-1], '%Y%m%d%H%M%S')
except (ValueError, IndexError):
raise Error(
"Expected a restricted generalized time string, but got '{}'.".format(
string))
def restricted_generalized_time_from_datetime(date):
"""Convert given ``datetime.datetime`` object `date` to an restricted
ASN.1 generalized time string.
"""
if date.tzinfo is not None:
date -= date.utcoffset()
if date.microsecond > 0:
string = date.strftime('%Y%m%d%H%M%S.%f').rstrip('0')
else:
string = date.strftime('%Y%m%d%H%M%S')
return string + 'Z'
def format_bytes(tag):
"""
Format tag as hex string
:param bytes tag:
:return:
"""
return tag.hex() asn1tools-0.169.0/asn1tools/codecs/ber.py 0000664 0000000 0000000 00000157362 15245442746 0020152 0 ustar 00root root 0000000 0000000 """Basic Encoding Rules (BER) codec.
"""
import time
import math
import binascii
from copy import copy
import datetime
from ..parser import EXTENSION_MARKER
from . import BaseType, format_bytes, DecodeError, ErrorWithLocation
from . import EncodeError
from . import DecodeError
from . import format_or
from . import compiler
from . import utc_time_to_datetime
from . import utc_time_from_datetime
from . import generalized_time_to_datetime
from . import generalized_time_from_datetime
from .compiler import enum_values_as_dict
from .compiler import clean_bit_string_value
class Class(object):
UNIVERSAL = 0x00
APPLICATION = 0x40
CONTEXT_SPECIFIC = 0x80
PRIVATE = 0xc0
class Encoding(object):
PRIMITIVE = 0x00
CONSTRUCTED = 0x20
class Tag(object):
END_OF_CONTENTS = 0x00
BOOLEAN = 0x01
INTEGER = 0x02
BIT_STRING = 0x03
OCTET_STRING = 0x04
NULL = 0x05
OBJECT_IDENTIFIER = 0x06
OBJECT_DESCRIPTOR = 0x07
EXTERNAL = 0x08
REAL = 0x09
ENUMERATED = 0x0a
EMBEDDED_PDV = 0x0b
UTF8_STRING = 0x0c
RELATIVE_OID = 0x0d
SEQUENCE = 0x10
SET = 0x11
NUMERIC_STRING = 0x12
PRINTABLE_STRING = 0x13
T61_STRING = 0x14
VIDEOTEX_STRING = 0x15
IA5_STRING = 0x16
UTC_TIME = 0x17
GENERALIZED_TIME = 0x18
GRAPHIC_STRING = 0x19
VISIBLE_STRING = 0x1a
GENERAL_STRING = 0x1b
UNIVERSAL_STRING = 0x1c
CHARACTER_STRING = 0x1d
BMP_STRING = 0x1e
DATE = 0x1f
TIME_OF_DAY = 0x20
DATE_TIME = 0x21
END_OF_CONTENTS_OCTETS = b'\x00\x00'
TAG_MISMATCH = object()
def flatten(l):
"""
Flatten irregular nested list
:param l:
:return:
"""
if isinstance(l, (list, tuple)):
return [a for i in l for a in flatten(i)]
else:
return [l]
def is_end_of_data(data, offset, end_offset):
# Detect end of data
if end_offset is not None:
if offset >= end_offset:
return True, offset
elif detect_end_of_contents_tag(data, offset):
return True, offset + 2
return False, offset
def detect_end_of_contents_tag(data, offset):
"""
Determine whether end of contents tag is present at offset in data
:param bytes data:
:param int offset:
:return:
"""
two_bytes = data[offset:offset + 2]
if two_bytes == END_OF_CONTENTS_OCTETS:
return True
# Detect missing data
elif len(two_bytes) != 2:
raise OutOfByteDataError(
'Ran out of data when trying to find End of Contents tag for indefinite length field',
offset=offset)
else:
return False
def check_decode_error(asn_type, decoded_value, data, offset):
"""
Checks if decode result corresponds to TAG_MISMATCH, if so, raise DecodeTagError
:return:
"""
if decoded_value == TAG_MISMATCH:
raise DecodeTagError(asn_type, data, offset, location=asn_type)
class MissingMandatoryFieldError(DecodeError):
"""
Error for when there is no data for a mandatory field member
"""
def __init__(self, member, offset):
super().__init__('{} is missing and has no default value'.format(member),
offset=offset,
location=member)
class OutOfByteDataError(DecodeError):
"""
Error for when running out of / missing data missing when attempting to decode
"""
pass
class MissingDataError(OutOfByteDataError):
"""
Special variant of OutOfByteDataError for when remaining data length is less than decoded element length
"""
def __init__(self, message, offset, expected_length, location=None):
super().__init__(message, offset, location=location)
self.expected_length = expected_length
class DecodeTagError(DecodeError):
"""
ASN.1 tag decode error for BER and DER codecs
"""
def __init__(self, asn_type, data, offset, location=None):
"""
:param StandardDecodeMixin, Type asn_type: ASN type instance error occurred for
:param bytes data: ASN data
:param int offset:
:param str location: Name of ASN1 element error occurred in
"""
self.actual_tag = format_bytes(read_tag(data, offset)
if asn_type.tag_len is None
else data[offset:offset + asn_type.tag_len])
self.asn_type = asn_type
tag = asn_type.format_tag()
message = "Expected {} with {}, but got '{}'.".format(
asn_type.type_label(),
'tags {}'.format(tag) if isinstance(tag, list) else "tag '{}'".format(tag),
self.actual_tag)
super(DecodeTagError, self).__init__(message, offset=offset, location=location)
class NoEndOfContentsTagError(DecodeError):
"""
Exception for when end-of-contents tag (00) could not be found for indefinite-length field
"""
pass
def encode_length_definite(length):
if length <= 127:
encoded = bytearray([length])
else:
encoded = bytearray()
while length > 0:
encoded.append(length & 0xff)
length >>= 8
encoded.append(0x80 | len(encoded))
encoded.reverse()
return encoded
def decode_length(encoded, offset, enforce_definite=True):
"""
Decode definite or indefinite length of an ASN.1 node
:param bytes encoded:
:param int offset:
:param bool enforce_definite: Whether to raise error if length is indefinite
:return:
"""
try:
length = encoded[offset]
except IndexError:
raise OutOfByteDataError('Ran out of data when trying to read length',
offset=offset)
offset += 1
if length & 0x80: # Faster than > 127
# Handle indefinite length
if length == 128:
if enforce_definite:
raise DecodeError('Expected definite length, but got indefinite.',
offset=offset - 1)
return None, offset
else:
# Handle long length
number_of_bytes = (length & 0x7f)
encoded_length = encoded[offset:number_of_bytes + offset]
# Verify all the length bytes exist
if len(encoded_length) != number_of_bytes:
raise OutOfByteDataError('Expected {} length byte(s) at offset {}, but got {}.'.format(
number_of_bytes, offset, len(encoded_length)),
offset=offset)
length = int(binascii.hexlify(encoded_length), 16)
offset += number_of_bytes
# Detect missing data
data_length = len(encoded)
if offset + length > data_length:
raise MissingDataError(
'Expected at least {} contents byte(s), but got {}.'.format(length, data_length - offset),
offset,
length
)
return length, offset
def encode_signed_integer(number):
byte_length = (8 + (number + (number < 0)).bit_length()) // 8
return number.to_bytes(length=byte_length, byteorder='big', signed=True)
def encode_tag(number, flags):
if number < 31:
tag = bytearray([flags | number])
else:
tag = bytearray([flags | 0x1f])
encoded = bytearray()
while number > 0:
encoded.append(0x80 | (number & 0x7f))
number >>= 7
encoded[0] &= 0x7f
encoded.reverse()
tag.extend(encoded)
return tag
def skip_tag(data, offset):
try:
byte = data[offset]
offset += 1
if byte & 0x1f == 0x1f:
while data[offset] & 0x80:
offset += 1
offset += 1
except IndexError:
raise OutOfByteDataError('Ran out of data when reading tag',
offset=offset)
if offset >= len(data):
raise OutOfByteDataError('Ran out of data when reading tag',
offset=offset)
return offset
def read_tag(data, offset):
return data[offset:skip_tag(data, offset)]
def skip_tag_length_contents(data, offset):
"""
Get offset position at end of node (skip tag, length and contents)
:param data:
:param offset:
:return:
"""
offset = skip_tag(data, offset)
return sum(decode_length(data, offset))
def encode_real(data):
if data == float('inf'):
data = b'\x40'
elif data == float('-inf'):
data = b'\x41'
elif math.isnan(data):
data = b'\x42'
elif data == 0.0:
data = b''
else:
if data >= 0:
negative_bit = 0
else:
negative_bit = 0x40
data *= -1
mantissa, exponent = math.frexp(abs(data))
mantissa = int(mantissa * 2 ** 53)
lowest_set_bit = compiler.lowest_set_bit(mantissa)
mantissa >>= lowest_set_bit
mantissa |= (0x80 << (8 * ((mantissa.bit_length() // 8) + 1)))
mantissa = binascii.unhexlify(hex(mantissa)[4:].rstrip('L'))
exponent = (52 - lowest_set_bit - exponent)
if -129 < exponent < 128:
exponent = [0x80 | negative_bit, ((0xff - exponent) & 0xff)]
elif -32769 < exponent < 32768:
exponent = ((0xffff - exponent) & 0xffff)
exponent = [0x81 | negative_bit, (exponent >> 8), exponent & 0xff]
else:
raise NotImplementedError(
'REAL exponent {} out of range.'.format(exponent))
data = bytearray(exponent) + mantissa
return data
def decode_real_binary(control, data):
if control in [0x80, 0xc0]:
exponent = data[1]
if exponent & 0x80:
exponent -= 0x100
offset = 2
elif control in [0x81, 0xc1]:
exponent = ((data[1] << 8) | data[2])
if exponent & 0x8000:
exponent -= 0x10000
offset = 3
else:
raise DecodeError(
'Unsupported binary REAL control word 0x{:02x}.'.format(control))
mantissa = int(binascii.hexlify(data[offset:]), 16)
decoded = float(mantissa * 2 ** exponent)
if control & 0x40:
decoded *= -1
return decoded
def decode_real_special(control):
try:
return {
0x40: float('inf'),
0x41: float('-inf'),
0x42: float('nan'),
0x43: -0.0
}[control]
except KeyError:
raise DecodeError(
'Unsupported special REAL control word 0x{:02x}.'.format(control))
def decode_real_decimal(data):
return float(data[1:].replace(b',', b'.'))
def decode_real(data):
if len(data) == 0:
decoded = 0.0
else:
control = data[0]
if control & 0x80:
decoded = decode_real_binary(control, data)
elif control & 0x40:
decoded = decode_real_special(control)
else:
decoded = decode_real_decimal(data)
return decoded
def encode_object_identifier(data):
identifiers = [int(identifier) for identifier in data.split('.')]
first_subidentifier = (40 * identifiers[0] + identifiers[1])
encoded_subidentifiers = encode_object_identifier_subidentifier(
first_subidentifier)
for identifier in identifiers[2:]:
encoded_subidentifiers += encode_object_identifier_subidentifier(
identifier)
return encoded_subidentifiers
def encode_object_identifier_subidentifier(subidentifier):
encoded = [subidentifier & 0x7f]
subidentifier >>= 7
while subidentifier > 0:
encoded.append(0x80 | (subidentifier & 0x7f))
subidentifier >>= 7
return encoded[::-1]
def decode_object_identifier(data, offset, end_offset):
subidentifier, offset = decode_object_identifier_subidentifier(data,
offset)
decoded = [subidentifier // 40, subidentifier % 40]
while offset < end_offset:
subidentifier, offset = decode_object_identifier_subidentifier(data,
offset)
decoded.append(subidentifier)
return '.'.join([str(v) for v in decoded])
def decode_object_identifier_subidentifier(data, offset):
decoded = 0
while data[offset] & 0x80:
decoded += (data[offset] & 0x7f)
decoded <<= 7
offset += 1
decoded += data[offset]
return decoded, offset + 1
class Type(BaseType):
"""
Base type class for BER types
"""
def __init__(self, name, type_name, number, flags=0):
"""
:param str name: Name of type instance
:param str type_name: ASN1 Type name
:param int number: Tag number
:param flags:
"""
super().__init__(name, type_name)
if number is None:
self.tag = None
self.tag_len = None
else:
self.tag = encode_tag(number, flags)
self.tag_len = len(self.tag)
def decode(self, data, offset, values=None):
"""
Decode type value from byte data
:param bytearray data: Binary ASN1 data to decode
:param int offset: Current byte offset
:param dict values:
:return: Tuple of (decoded_value, end_offset)
"""
raise NotImplementedError()
def encode(self, data, encoded, values=None):
"""
Encode value into byte data
:param data: Value to be encoded
:param bytearray encoded: Existing byte data to add encoded data to
:param values:
:return: None (extend 'encoded' bytearray)
"""
raise NotImplementedError()
def set_tag(self, number, flags):
self.tag = encode_tag(number, flags)
self.tag_len = len(self.tag)
def format_tag(self):
"""
Get formatted hex string representation of this type's tag
:return:
"""
return format_bytes(self.tag) if self.tag is not None else '(Unknown)'
def set_size_range(self, minimum, maximum, has_extension_marker):
pass
class StandardDecodeMixin(object):
"""
Type class mixin for standard decoding logic
(single predefined tag to be matched against, then decode length and contents)
"""
indefinite_allowed = False # Whether indefinite length encoding is allowed for this type
def decode(self, data, offset, values=None):
"""
Implements standard decode logic (single predefined tag to be matched against, then decode length and contents)
:param bytearray data: Binary ASN1 data to decode
:param int offset: Current byte offset
:param dict values:
:return: Tuple of (decoded_value, end_offset)
"""
start_offset = offset
offset += self.tag_len
# Validate tag
tag_data = data[start_offset:offset]
if tag_data != self.tag:
# Check for missing data
if len(tag_data) != self.tag_len:
raise OutOfByteDataError('Ran out of data when reading tag',
offset=start_offset)
# return TAG_MISMATCH Instead of raising DecodeTagError for better performance so that MembersType does
# not have to catch exception for every missing optional type
# CompiledType.decode_with_length() will detect TAG_MISMATCH returned value and raise appropriate exception
return TAG_MISMATCH, start_offset
# Decode length
length, offset = decode_length(data, offset, enforce_definite=not self.indefinite_allowed)
return self.decode_content(data, offset, length)
def decode_content(self, data, offset, length):
"""
Type-specific logic to decode content
:param bytearray data: Binary data to decode
:param int offset: Offset for start of content bytes
:param int length: Length of content bytes (None if indefinite)
:return: Tuple of (decoded_value, end_offset)
"""
raise NotImplementedError('Type {} does not implement decode_content() method'.format(type(self).__name__))
class StandardEncodeMixin(object):
"""
Type class mixin for standard encoding logic (append tag + length(content) + content)
"""
def encode(self, data, encoded, values=None):
"""
Encode value into byte data
:param data: Value to be encoded
:param bytearray encoded: Existing byte data to add encoded data to
:param values:
:return:
"""
encoded_data = bytearray(self.encode_content(data, values=values))
encoded.extend(self.tag + encode_length_definite(len(encoded_data)) + encoded_data)
def encode_content(self, data, values=None):
"""
Encode data value into bytearray
:param data:
:param values:
:return:
"""
raise NotImplementedError()
class PrimitiveOrConstructedType(Type):
"""
Base type class for types which can be either primitive or constructed (BitString, OctetString, String)
"""
def __init__(self, name, type_name, number, segment, flags=0):
super(PrimitiveOrConstructedType, self).__init__(name,
type_name,
number,
flags)
self.segment = segment
self.constructed_tag = copy(self.tag)
self.constructed_tag[0] |= Encoding.CONSTRUCTED
def set_tag(self, number, flags):
self.tag = encode_tag(number, flags)
self.constructed_tag = copy(self.tag)
self.constructed_tag[0] |= Encoding.CONSTRUCTED
self.tag_len = len(self.tag)
def decode(self, data, start_offset, values=None):
"""
Custom decode logic to handle primitive or constructed types
Return decoded value and new offset
"""
offset = start_offset + self.tag_len
tag = data[start_offset:offset]
# Validate tag
if tag == self.tag:
is_primitive = True
elif tag == self.constructed_tag:
is_primitive = False
elif len(tag) != self.tag_len:
# Detect out of data
raise OutOfByteDataError('Ran out of data when reading tag',
offset=start_offset)
else:
# Tag mismatch. Return DECODE_FAILED instead of raising DecodeError for performance
return TAG_MISMATCH, start_offset
length, offset = decode_length(data, offset, enforce_definite=False)
if is_primitive:
end_offset = offset + length
return self.decode_primitive_contents(data, offset, length), end_offset
else:
return self.decode_constructed_contents(data, offset, length)
def decode_constructed_contents(self, data, offset, length):
segments = []
end_offset = None if length is None else offset + length
while True:
end_of_data, offset = is_end_of_data(data, offset, end_offset)
if end_of_data:
break
decoded, offset = self.segment.decode(data, offset)
check_decode_error(self.segment, decoded, data, offset)
segments.append(decoded)
return self.decode_constructed_segments(segments), offset
def decode_primitive_contents(self, data, offset, length):
raise NotImplementedError('To be implemented by subclasses.')
def decode_constructed_segments(self, segments):
raise NotImplementedError('To be implemented by subclasses.')
class StringType(StandardEncodeMixin, PrimitiveOrConstructedType):
TAG = None
ENCODING = None
def __init__(self, name):
super(StringType, self).__init__(name,
self.__class__.__name__,
self.TAG,
OctetString(name))
def encode_content(self, data, values=None):
return data.encode(self.ENCODING)
def decode_primitive_contents(self, data, offset, length):
return data[offset:offset + length].decode(self.ENCODING)
def decode_constructed_segments(self, segments):
return bytearray().join(segments).decode(self.ENCODING)
class MembersType(StandardEncodeMixin, StandardDecodeMixin, Type):
indefinite_allowed = True
def __init__(self, name, tag_name, tag, root_members, additions):
super(MembersType, self).__init__(name,
tag_name,
tag,
Encoding.CONSTRUCTED)
self.root_members = root_members
self.additions = additions
def set_tag(self, number, flags):
super(MembersType, self).set_tag(number,
flags | Encoding.CONSTRUCTED)
def encode_content(self, data, values=None):
encoded_members = bytearray()
for member in self.root_members:
self.encode_member(member, data, encoded_members)
if self.additions:
self.encode_additions(data, encoded_members)
return encoded_members
def encode_additions(self, data, encoded_members):
try:
for addition in self.additions:
encoded_addition = bytearray()
if isinstance(addition, list):
for member in addition:
self.encode_member(member, data, encoded_addition)
else:
self.encode_member(addition,
data,
encoded_addition)
encoded_members.extend(encoded_addition)
except EncodeError:
pass
def encode_member(self, member, data, encoded_members):
name = member.name
if name in data:
value = data[name]
try:
if isinstance(member, AnyDefinedBy):
member.encode(value, encoded_members, data)
elif not member.is_default(value):
member.encode(value, encoded_members)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
elif member.optional:
pass
elif not member.has_default():
raise EncodeError("{} member '{}' not found in {}.".format(
self.__class__.__name__,
name,
data))
def decode_content(self, data, offset, length):
end_offset = None if length is None else offset + length
values = {}
offset, out_of_data = self.decode_members(self.root_members, data, values, offset, end_offset)
# Decode additions (even if out of data already, so defaults can be added)
if self.additions:
offset, out_of_data = self.decode_members(flatten(self.additions), data, values, offset, end_offset,
ignore_missing=True)
if out_of_data:
return values, offset
if end_offset is None:
raise NoEndOfContentsTagError('Could not find end-of-contents tag for indefinite length field.',
offset=offset)
else:
# Extra data is allowed in cases of versioned additions
return values, end_offset
def decode_members(self, members, data, values, offset, end_offset, ignore_missing=False):
"""
Decode values for members from data starting from offset
Supports member data encoded in different order than members specified
:param list members: List of member types
:param bytearray data:
:param dict values:
:param int offset:
:param int end_offset: End offset of member data (None if indefinite length field)
:param bool ignore_missing: Whether to not raise DecodeError for missing mandatory fields with no defaults
:return:
"""
# Decode member values from data
remaining_members = members
# Outer loop to enable decoding members out of order
while True:
undecoded_members = []
decode_success = False # Whether at least one member was successfully decoded
out_of_data, offset = is_end_of_data(data, offset, end_offset)
# Attempt to decode remaining members. If they are encoded in same order, should decode all in one loop
# Otherwise will require multiple iterations of outer loop
for member in remaining_members:
# Dont attempt decode if already out of data, just add member to list of undecoded
if out_of_data:
undecoded_members.append(member)
continue
# Attempt decode
try:
value, offset = member.decode(data, offset, values=values)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
if value == TAG_MISMATCH:
undecoded_members.append(member)
else:
decode_success = True
values[member.name] = value
# Detect end of data
out_of_data, offset = is_end_of_data(data, offset, end_offset)
remaining_members = undecoded_members
if out_of_data:
break
if not decode_success:
# No members are able to decode data, exit loop
break
# Handle remaining members that there is no data for
# (will raise error if member is not optional and has no default)
for member in remaining_members:
if member.optional:
continue
if member.has_default():
values[member.name] = member.get_default()
elif ignore_missing:
break
elif out_of_data:
raise MissingMandatoryFieldError(member, offset)
else:
raise DecodeTagError(member, data, offset, location=member)
return offset, out_of_data
def __repr__(self):
return '{}({}, [{}])'.format(
self.__class__.__name__,
self.name,
', '.join([repr(member) for member in self.root_members]))
class ArrayType(StandardEncodeMixin, StandardDecodeMixin, Type):
indefinite_allowed = True
def __init__(self, name, tag_name, tag, element_type):
super(ArrayType, self).__init__(name,
tag_name,
tag,
Encoding.CONSTRUCTED)
self.element_type = element_type
def set_tag(self, number, flags):
super(ArrayType, self).set_tag(number,
flags | Encoding.CONSTRUCTED)
def encode_content(self, data, values=None):
encoded_elements = bytearray()
for entry in data:
self.element_type.encode(entry, encoded_elements)
return encoded_elements
def decode_content(self, data, offset, length):
decoded = []
start_offset = offset
# Loop through data until length exceeded or end-of-contents tag reached.
while True:
if length is None:
# Find end of indefinite sequence.
if detect_end_of_contents_tag(data, offset):
offset += 2
break
elif (offset - start_offset) >= length:
# End of definite length sequence.
break
decoded_element, offset = self.element_type.decode(data, offset)
# Invalid Tag
check_decode_error(self.element_type, decoded_element, data, offset)
decoded.append(decoded_element)
return decoded, offset
def __repr__(self):
return '{}({}, {})'.format(self.__class__.__name__,
self.name,
self.element_type)
class Boolean(StandardEncodeMixin, StandardDecodeMixin, Type):
def __init__(self, name):
super(Boolean, self).__init__(name,
'BOOLEAN',
Tag.BOOLEAN)
def encode_content(self, data, values=None):
return bytearray([0xff * data])
def decode_content(self, data, offset, length):
if length != 1:
raise DecodeError(
'Expected BOOLEAN contents length 1, but '
'got {}.'.format(length), offset=offset-1)
return bool(data[offset]), offset + length
class Integer(StandardEncodeMixin, StandardDecodeMixin, Type):
def __init__(self, name):
super(Integer, self).__init__(name,
'INTEGER',
Tag.INTEGER)
def encode_content(self, data, values=None):
return encode_signed_integer(data)
def decode_content(self, data, offset, length):
end_offset = offset + length
return int.from_bytes(data[offset:end_offset], byteorder='big', signed=True), end_offset
class Real(StandardEncodeMixin, StandardDecodeMixin, Type):
def __init__(self, name):
super(Real, self).__init__(name, 'REAL', Tag.REAL)
def encode_content(self, data, values=None):
return encode_real(data)
def decode_content(self, data, offset, length):
end_offset = offset + length
decoded = decode_real(data[offset:end_offset])
return decoded, end_offset
class Null(StandardDecodeMixin, Type):
def __init__(self, name):
super(Null, self).__init__(name, 'NULL', Tag.NULL)
def is_default(self, value):
return False
def encode(self, _, encoded):
encoded.extend(self.tag)
encoded.append(0)
def decode_content(self, data, offset, length):
return None, offset
class BitString(StandardEncodeMixin, PrimitiveOrConstructedType):
def __init__(self, name, has_named_bits):
super(BitString, self).__init__(name,
'BIT STRING',
Tag.BIT_STRING,
self)
self.has_named_bits = has_named_bits
def is_default(self, value):
if self.default is None:
return False
clean_value = clean_bit_string_value(value,
self.has_named_bits)
clean_default = clean_bit_string_value(self.default,
self.has_named_bits)
return clean_value == clean_default
def encode_content(self, data, values=None):
number_of_bytes, number_of_rest_bits = divmod(data[1], 8)
data = bytearray(data[0])
if number_of_rest_bits == 0:
data = data[:number_of_bytes]
number_of_unused_bits = 0
else:
last_byte = data[number_of_bytes]
last_byte &= ((0xff >> number_of_rest_bits) ^ 0xff)
data = data[:number_of_bytes]
data.append(last_byte)
number_of_unused_bits = (8 - number_of_rest_bits)
return bytearray([number_of_unused_bits]) + data
def decode_primitive_contents(self, data, offset, length):
length -= 1
number_of_bits = 8 * length - data[offset]
offset += 1
return (data[offset:offset + length], number_of_bits)
def decode_constructed_segments(self, segments):
decoded = bytearray()
number_of_bits = 0
for data, length in segments:
decoded.extend(data)
number_of_bits += length
return (bytes(decoded), number_of_bits)
class OctetString(StandardEncodeMixin, PrimitiveOrConstructedType):
def __init__(self, name):
super(OctetString, self).__init__(name,
'OCTET STRING',
Tag.OCTET_STRING,
self)
def encode_content(self, data, values=None):
return data
def decode_primitive_contents(self, data, offset, length):
return bytes(data[offset:offset + length])
def decode_constructed_segments(self, segments):
return bytes().join(segments)
class ObjectIdentifier(StandardEncodeMixin, StandardDecodeMixin, Type):
def __init__(self, name):
super(ObjectIdentifier, self).__init__(name,
'OBJECT IDENTIFIER',
Tag.OBJECT_IDENTIFIER)
def encode_content(self, data, values=None):
return encode_object_identifier(data)
def decode_content(self, data, offset, length):
end_offset = offset + length
decoded = decode_object_identifier(data, offset, end_offset)
return decoded, end_offset
class Enumerated(StandardEncodeMixin, StandardDecodeMixin, Type):
def __init__(self, name, values, numeric):
super(Enumerated, self).__init__(name,
'ENUMERATED',
Tag.ENUMERATED)
if numeric:
self.value_to_data = {k: k for k in enum_values_as_dict(values)}
self.data_to_value = self.value_to_data
else:
self.value_to_data = enum_values_as_dict(values)
self.data_to_value = {v: k for k, v in self.value_to_data.items()}
self.has_extension_marker = (EXTENSION_MARKER in values)
def format_names(self):
return format_or(sorted(list(self.value_to_data.values())))
def format_values(self):
return format_or(sorted(list(self.value_to_data)))
def encode_content(self, data, values=None):
try:
value = self.data_to_value[data]
except KeyError:
raise EncodeError(
"Expected enumeration value {}, but got '{}'.".format(
self.format_names(),
data))
return encode_signed_integer(value)
def decode_content(self, data, offset, length):
end_offset = offset + length
value = int.from_bytes(data[offset:end_offset], byteorder='big', signed=True)
if value in self.value_to_data:
return self.value_to_data[value], end_offset
elif self.has_extension_marker:
return None, end_offset
else:
raise DecodeError(
'Expected enumeration value {}, but got {}.'.format(
self.format_values(),
value), offset=offset)
class Sequence(MembersType):
def __init__(self, name, root_members, additions):
super(Sequence, self).__init__(name,
'SEQUENCE',
Tag.SEQUENCE,
root_members,
additions)
class SequenceOf(ArrayType):
def __init__(self, name, element_type):
super(SequenceOf, self).__init__(name,
'SEQUENCE OF',
Tag.SEQUENCE,
element_type)
class Set(MembersType):
def __init__(self, name, root_members, additions):
super(Set, self).__init__(name,
'SET',
Tag.SET,
root_members,
additions)
class SetOf(ArrayType):
def __init__(self, name, element_type):
super(SetOf, self).__init__(name,
'SET OF',
Tag.SET,
element_type)
class Choice(Type):
def __init__(self, name, root_members, additions):
super(Choice, self).__init__(name, 'CHOICE', None)
members = root_members
if additions is not None:
for addition in additions:
if isinstance(addition, list):
members += addition
else:
members.append(addition)
self.has_extension_marker = True
else:
self.has_extension_marker = False
self.members = members
self.name_to_member = {member.name: member for member in self.members}
self.tag_to_member = {}
self.add_tags(self.members)
def add_tags(self, members):
for member in members:
tags = self.get_member_tags(member)
for tag in tags:
self.tag_to_member[tag] = member
def get_member_tags(self, member):
tags = []
if isinstance(member, Choice):
tags = self.get_choice_tags(member)
elif isinstance(member, Recursive):
if member.inner is None:
member.choice_parents.append(self)
else:
tags = self.get_member_tags(member.inner)
else:
tags.append(bytes(member.tag))
if hasattr(member, 'constructed_tag'):
tags.append(bytes(member.constructed_tag))
return tags
def get_choice_tags(self, choice):
tags = []
for member in choice.members:
tags.extend(self.get_member_tags(member))
return tags
def format_tag(self):
return [format_bytes(tag) for tag in self.tag_to_member]
def format_names(self):
return format_or(sorted([member.name for member in self.members]))
def encode(self, data, encoded, values=None):
try:
member = self.name_to_member[data[0]]
except KeyError:
raise EncodeError(
"Expected choice {}, but got '{}'.".format(
self.format_names(),
data[0]))
try:
member.encode(data[1], encoded)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
def decode(self, data, offset, values=None):
tag = bytes(read_tag(data, offset))
if tag in self.tag_to_member:
member = self.tag_to_member[tag]
elif self.has_extension_marker:
offset = skip_tag_length_contents(data, offset)
return (None, None), offset
else:
return TAG_MISMATCH, offset
try:
decoded, offset = member.decode(data, offset)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
return (member.name, decoded), offset
def __repr__(self):
return 'Choice({}, [{}])'.format(
self.name,
', '.join([repr(member) for member in self.members]))
class UTF8String(StringType):
TAG = Tag.UTF8_STRING
ENCODING = 'utf-8'
class NumericString(StringType):
TAG = Tag.NUMERIC_STRING
ENCODING = 'ascii'
class PrintableString(StringType):
TAG = Tag.PRINTABLE_STRING
ENCODING = 'ascii'
class IA5String(StringType):
TAG = Tag.IA5_STRING
ENCODING = 'ascii'
class VisibleString(StringType):
TAG = Tag.VISIBLE_STRING
ENCODING = 'ascii'
class GeneralString(StringType):
TAG = Tag.GENERAL_STRING
ENCODING = 'latin-1'
class BMPString(StringType):
TAG = Tag.BMP_STRING
ENCODING = 'utf-16-be'
class GraphicString(StringType):
TAG = Tag.GRAPHIC_STRING
ENCODING = 'latin-1'
class UniversalString(StringType):
TAG = Tag.UNIVERSAL_STRING
ENCODING = 'utf-32-be'
class TeletexString(StringType):
TAG = Tag.T61_STRING
ENCODING = 'iso-8859-1'
class ObjectDescriptor(GraphicString):
TAG = Tag.OBJECT_DESCRIPTOR
class UTCTime(StandardEncodeMixin, StandardDecodeMixin, Type):
def __init__(self, name):
super(UTCTime, self).__init__(name,
'UTCTime',
Tag.UTC_TIME)
def encode_content(self, data, values=None):
return utc_time_from_datetime(data).encode('ascii')
def decode_content(self, data, offset, length):
end_offset = offset + length
decoded = data[offset:end_offset].decode('ascii')
return utc_time_to_datetime(decoded), end_offset
class GeneralizedTime(StandardEncodeMixin, StandardDecodeMixin, Type):
def __init__(self, name):
super(GeneralizedTime, self).__init__(name,
'GeneralizedTime',
Tag.GENERALIZED_TIME)
def encode_content(self, data, values=None):
return generalized_time_from_datetime(data).encode('ascii')
def decode_content(self, data, offset, length):
end_offset = offset + length
decoded = data[offset:end_offset].decode('ascii')
return generalized_time_to_datetime(decoded), end_offset
class Date(StandardEncodeMixin, StandardDecodeMixin, Type):
def __init__(self, name):
super(Date, self).__init__(name, 'DATE', Tag.DATE)
def encode_content(self, data, values=None):
return str(data).replace('-', '').encode('ascii')
def decode_content(self, data, offset, length):
end_offset = offset + length
decoded = data[offset:end_offset].decode('ascii')
decoded = datetime.date(*time.strptime(decoded, '%Y%m%d')[:3])
return decoded, end_offset
class TimeOfDay(StandardEncodeMixin, StandardDecodeMixin, Type):
def __init__(self, name):
super(TimeOfDay, self).__init__(name,
'TIME-OF-DAY',
Tag.TIME_OF_DAY)
def encode_content(self, data, values=None):
return str(data).replace(':', '').encode('ascii')
def decode_content(self, data, offset, length):
end_offset = offset + length
decoded = data[offset:end_offset].decode('ascii')
decoded = datetime.time(*time.strptime(decoded, '%H%M%S')[3:6])
return decoded, end_offset
class DateTime(StandardEncodeMixin, StandardDecodeMixin, Type):
def __init__(self, name):
super(DateTime, self).__init__(name,
'DATE-TIME',
Tag.DATE_TIME)
def encode_content(self, data, values=None):
return '{:04d}{:02d}{:02d}{:02d}{:02d}{:02d}'.format(*data.timetuple()).encode('ascii')
def decode_content(self, data, offset, length):
end_offset = offset + length
decoded = data[offset:end_offset].decode('ascii')
decoded = datetime.datetime(*time.strptime(decoded, '%Y%m%d%H%M%S')[:6])
return decoded, end_offset
class Any(Type):
def __init__(self, name):
super(Any, self).__init__(name, 'ANY', None)
def encode(self, data, encoded):
encoded.extend(data)
def decode(self, data, offset, values=None):
start = offset
offset = skip_tag(data, offset)
length, offset = decode_length(data, offset)
end_offset = offset + length
return data[start:end_offset], end_offset
class AnyDefinedBy(Type):
def __init__(self, name, type_member, choices):
super(AnyDefinedBy, self).__init__(name,
'ANY DEFINED BY',
None,
None)
self.type_member = type_member
self.choices = choices
def encode(self, data, encoded, values):
if self.choices:
try:
self.choices[values[self.type_member]].encode(data, encoded)
except KeyError:
raise EncodeError('Bad AnyDefinedBy choice {}.'.format(
values[self.type_member]))
else:
encoded.extend(data)
def decode(self, data, offset, values):
"""
:param data:
:param int offset: Byte offset in ASN1 data
:param dict values: Dictionary of already decoded values in containing type
:return:
"""
if self.choices:
try:
return self.choices[values[self.type_member]].decode(data,
offset)
except KeyError:
raise DecodeError('Bad AnyDefinedBy choice {}.'.format(
values[self.type_member]),
offset=offset)
else:
start = offset
offset = skip_tag(data, offset)
length, offset = decode_length(data, offset)
end_offset = offset + length
return data[start:end_offset], end_offset
class ExplicitTag(StandardEncodeMixin, StandardDecodeMixin, Type):
# no_error_location = True
indefinite_allowed = True
def __init__(self, name, inner):
super(ExplicitTag, self).__init__(name, 'ExplicitTag', None)
self.inner = inner
def set_default(self, value):
self.inner.set_default(value)
def get_default(self):
return self.inner.get_default()
def is_default(self, value):
return self.inner.is_default(value)
def has_default(self):
return self.inner.has_default()
def set_tag(self, number, flags):
super(ExplicitTag, self).set_tag(number,
flags | Encoding.CONSTRUCTED)
def encode_content(self, data, values=None):
encoded_inner = bytearray()
self.inner.encode(data, encoded_inner)
return encoded_inner
def decode_content(self, data, offset, length):
values, end_offset = self.inner.decode(data, offset)
check_decode_error(self.inner, values, data, offset)
# Verify End of Contents tag exists for Indefinite field
if length is None:
if not detect_end_of_contents_tag(data, end_offset):
raise NoEndOfContentsTagError('Expected end-of-contents tag.',
offset=end_offset,
location=self)
end_offset += 2
return values, end_offset
class Recursive(compiler.Recursive, Type):
def __init__(self, name, type_name, module_name):
super(Recursive, self).__init__(name, 'RECURSIVE', None)
self.type_name = type_name
self.module_name = module_name
self.tag_number = None
self.tag_flags = None
self.inner = None
self.choice_parents = []
def set_tag(self, number, flags):
self.tag_number = number
self.tag_flags = flags
def set_inner_type(self, inner):
self.inner = copy(inner)
if self.tag_number is not None:
self.inner.set_tag(self.tag_number, self.tag_flags)
for choice_parent in self.choice_parents:
choice_parent.add_tags([self])
def encode(self, data, encoded, values=None):
self.inner.encode(data, encoded)
def decode(self, data, offset, values=None):
return self.inner.decode(data, offset)
class CompiledType(compiler.CompiledType):
def encode(self, data):
encoded = bytearray()
try:
self._type.encode(data, encoded)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
return encoded
def decode(self, data):
return self.decode_with_length(data)[0]
def decode_with_length(self, data):
"""
Decode and return decoded values as well as length of binary data decoded
:param data:
:return:
"""
try:
decoded, offset = self._type.decode(bytearray(data), 0)
# Raise DecodeError
check_decode_error(self._type, decoded, data, offset)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
return decoded, offset
def get_tag_no_encoding(member):
value = (member.tag[0] & ~Encoding.CONSTRUCTED)
return bytearray([value]) + member.tag[1:]
class Compiler(compiler.Compiler):
def process_type(self, type_name, type_descriptor, module_name):
compiled_type = self.compile_type(type_name,
type_descriptor,
module_name)
return CompiledType(compiled_type)
def compile_implicit_type(self, name, type_descriptor, module_name):
type_name = type_descriptor['type']
if type_name == 'SEQUENCE':
compiled = Sequence(
name,
*self.compile_members(type_descriptor['members'],
module_name))
elif type_name == 'SEQUENCE OF':
compiled = SequenceOf(name,
self.compile_type('',
type_descriptor['element'],
module_name))
elif type_name == 'SET':
compiled = Set(
name,
*self.compile_members(type_descriptor['members'],
module_name,
sort_by_tag=True))
elif type_name == 'SET OF':
compiled = SetOf(name,
self.compile_type('',
type_descriptor['element'],
module_name))
elif type_name == 'CHOICE':
compiled = Choice(
name,
*self.compile_members(type_descriptor['members'],
module_name))
elif type_name == 'INTEGER':
compiled = Integer(name)
elif type_name == 'REAL':
compiled = Real(name)
elif type_name == 'ENUMERATED':
compiled = Enumerated(name,
self.get_enum_values(type_descriptor,
module_name),
self._numeric_enums)
elif type_name == 'BOOLEAN':
compiled = Boolean(name)
elif type_name == 'OBJECT IDENTIFIER':
compiled = ObjectIdentifier(name)
elif type_name == 'OCTET STRING':
compiled = OctetString(name)
elif type_name == 'TeletexString':
compiled = TeletexString(name)
elif type_name == 'NumericString':
compiled = NumericString(name)
elif type_name == 'PrintableString':
compiled = PrintableString(name)
elif type_name == 'IA5String':
compiled = IA5String(name)
elif type_name == 'VisibleString':
compiled = VisibleString(name)
elif type_name == 'GeneralString':
compiled = GeneralString(name)
elif type_name == 'UTF8String':
compiled = UTF8String(name)
elif type_name == 'BMPString':
compiled = BMPString(name)
elif type_name == 'GraphicString':
compiled = GraphicString(name)
elif type_name == 'UTCTime':
compiled = UTCTime(name)
elif type_name == 'UniversalString':
compiled = UniversalString(name)
elif type_name == 'GeneralizedTime':
compiled = GeneralizedTime(name)
elif type_name == 'DATE':
compiled = Date(name)
elif type_name == 'TIME-OF-DAY':
compiled = TimeOfDay(name)
elif type_name == 'DATE-TIME':
compiled = DateTime(name)
elif type_name == 'BIT STRING':
has_named_bits = ('named-bits' in type_descriptor)
compiled = BitString(name, has_named_bits)
elif type_name == 'ANY':
compiled = Any(name)
elif type_name == 'ANY DEFINED BY':
choices = {}
for key, value in type_descriptor['choices'].items():
choices[key] = self.compile_type(key,
value,
module_name)
compiled = AnyDefinedBy(name,
type_descriptor['value'],
choices)
elif type_name == 'NULL':
compiled = Null(name)
elif type_name == 'EXTERNAL':
compiled = Sequence(
name,
*self.compile_members(self.external_type_descriptor()['members'],
module_name))
compiled.set_tag(Tag.EXTERNAL, 0)
elif type_name == 'ObjectDescriptor':
compiled = ObjectDescriptor(name)
else:
if type_name in self.types_backtrace:
compiled = Recursive(name,
type_name,
module_name)
self.recursive_types.append(compiled)
else:
compiled = self.compile_user_type(name,
type_name,
module_name)
return compiled
def compile_type(self, name, type_descriptor, module_name):
module_name = self.get_module_name(type_descriptor, module_name)
compiled = self.compile_implicit_type(name,
type_descriptor,
module_name)
if self.is_explicit_tag(type_descriptor):
compiled = ExplicitTag(name, compiled)
# Set any given tag.
if 'tag' in type_descriptor:
compiled = self.copy(compiled)
tag = type_descriptor['tag']
class_ = tag.get('class', None)
if class_ == 'APPLICATION':
flags = Class.APPLICATION
elif class_ == 'PRIVATE':
flags = Class.PRIVATE
elif class_ == 'UNIVERSAL':
flags = 0
else:
flags = Class.CONTEXT_SPECIFIC
compiled.set_tag(tag['number'], flags)
return compiled
def compile_members(self,
members,
module_name,
sort_by_tag=False):
compiled_members = []
in_extension = False
additions = None
for member in members:
if member == EXTENSION_MARKER:
in_extension = not in_extension
if in_extension:
additions = []
elif in_extension:
self.compile_extension_member(member,
module_name,
additions)
else:
self.compile_root_member(member,
module_name,
compiled_members)
if sort_by_tag:
compiled_members = sorted(compiled_members, key=get_tag_no_encoding)
return compiled_members, additions
def compile_extension_member(self,
member,
module_name,
additions):
if isinstance(member, list):
compiled_group = []
for memb in member:
compiled_member = self.compile_member(memb,
module_name)
compiled_group.append(compiled_member)
additions.append(compiled_group)
else:
compiled_member = self.compile_member(member,
module_name)
additions.append(compiled_member)
def compile_dict(specification, numeric_enums=False):
return Compiler(specification, numeric_enums).process()
def decode_full_length(data):
"""
Get total byte length of ASN1 element (tag + contents length)
:param data:
:return:
"""
try:
return skip_tag_length_contents(bytearray(data), 0)
except MissingDataError as e:
return e.offset + e.expected_length
except OutOfByteDataError:
return None
asn1tools-0.169.0/asn1tools/codecs/compiler.py 0000664 0000000 0000000 00000120344 15245442746 0021202 0 ustar 00root root 0000000 0000000 """Base Compiler class used by all codecs.
"""
import binascii
import sys
from operator import attrgetter
import bitstruct
from copy import copy
from copy import deepcopy
from ..errors import CompileError
from ..parser import EXTENSION_MARKER
def flatten(dlist):
flist = []
for item in dlist:
if isinstance(item, list):
flist.extend(item)
else:
flist.append(item)
return flist
def is_object_class_type_name(type_name):
return '&' in type_name
def is_open_type(type_name):
index = type_name.find('&')
if index == -1:
return False
return type_name[index + 1].isupper()
def is_type_name(type_name):
"""Does not handle keywords.
"""
return type_name[0].isupper()
def lowest_set_bit(value):
offset = (value & -value).bit_length() - 1
if offset < 0:
offset = 0
return offset
def rstrip_bit_string_zeros(data):
data = data.rstrip(b'\x00')
if len(data) == 0:
number_of_bits = 0
else:
number_of_bits = 8 * len(data) - lowest_set_bit(data[-1])
return (data, number_of_bits)
def clean_bit_string_value(value, has_named_bits):
data = bytearray(value[0])
number_of_bits = value[1]
number_of_bytes, number_of_rest_bits = divmod(number_of_bits, 8)
if number_of_rest_bits == 0:
data = data[:number_of_bytes]
else:
data = data[:number_of_bytes + 1]
data[number_of_bytes] &= ((0xff >> number_of_rest_bits) ^ 0xff)
if has_named_bits:
return rstrip_bit_string_zeros(data)
else:
return (data, number_of_bits)
class CompiledType(object):
def __init__(self, type_):
self.constraints_checker = None
self.type_checker = None
self._type = type_
@property
def type(self):
return self._type
@property
def name(self):
return self._type.name
def check_types(self, data):
return self.type_checker.encode(data)
def check_constraints(self, data):
return self.constraints_checker.encode(data)
def encode(self, data):
raise NotImplementedError('This codec does not support encode().')
def decode(self, data):
raise NotImplementedError('This codec does not support decode().')
def decode_with_length(self, data):
raise NotImplementedError('This codec does not support decode_with_length().')
def __repr__(self):
return repr(self._type)
class Recursive(object):
"""
Mixin used to identify Recursive types
"""
def __repr__(self):
return '{}({})'.format(type(self).__name__,
self.type_name)
class OpenType(object):
def __init__(self, name, table):
self._name = name
self._object_set_name = table[0]
self._table = []
for item in table[1]:
offset = item.count('.')
offset *= -1
self._table.append((offset, item.lstrip('.')))
def __repr__(self):
return 'OpenType({}, {}, {})'.format(self._name,
self._object_set_name,
self._table)
class OpenTypeSequence(object):
def __init__(self, name, members):
self._name = name
self._members = members
def __repr__(self):
return 'OpenTypeSequence({}, {})'.format(self._name, self._members)
class OpenTypeSequenceOf(object):
def __init__(self, name, element_type):
self._name = name
self._element_type = element_type
def __repr__(self):
return 'OpenTypeSequenceOf({}, {})'.format(self._name,
self._element_type)
class CompiledOpenTypes(CompiledType):
def __init__(self, compiled_open_types, compiled_type):
super(CompiledOpenTypes, self).__init__(compiled_type)
self._compiled_open_types = compiled_open_types
@property
def type(self):
return self._type.type
def encode(self, data, **kwargs):
# print()
# print('data:', data)
# print(self._compiled_open_types)
return self._type.encode(data, **kwargs)
def decode(self, data):
return self._type.decode(data)
class Compiler(object):
def __init__(self, specification, numeric_enums=False):
self._specification = specification
self._numeric_enums = numeric_enums
self._types_backtrace = []
self.recursive_types = []
self.compiled = {}
self.current_type_descriptor = None
def types_backtrace_push(self, type_name):
self._types_backtrace.append(type_name)
def types_backtrace_pop(self):
self._types_backtrace.pop()
@property
def types_backtrace(self):
return self._types_backtrace
def process(self):
self.pre_process()
compiled = {}
for module_name in self._specification:
items = self._specification[module_name]['types'].items()
for type_name, type_descriptor in items:
self.types_backtrace_push(type_name)
compiled_type = self.process_type(type_name,
type_descriptor,
module_name)
compiled_type.type_name = type_name
compiled_type.module_name = module_name
compiled_open_types = self.compile_open_types(type_name,
type_descriptor,
module_name)
if compiled_open_types:
compiled_type = CompiledOpenTypes(compiled_open_types,
compiled_type)
self.types_backtrace_pop()
if module_name not in compiled:
compiled[module_name] = {}
compiled[module_name][type_name] = compiled_type
for recursive_type in self.recursive_types:
compiled_module = compiled[recursive_type.module_name]
inner_type = compiled_module[recursive_type.type_name].type
recursive_type.set_inner_type(inner_type)
return compiled
def pre_process(self):
for module_name, module in self._specification.items():
types = module['types']
type_descriptors = types.values()
self.pre_process_components_of(type_descriptors, module_name)
self.pre_process_extensibility_implied(module, type_descriptors)
self.pre_process_tags(module, module_name)
self.pre_process_default_value(type_descriptors, module_name)
for module_name, module in self._specification.items():
self.pre_process_parameterization_step_1(module['types'],
module_name)
for module_name, module in self._specification.items():
types = module['types']
types = self.pre_process_parameterization_step_2(types)
module['types'] = types
return self._specification
def pre_process_components_of(self, type_descriptors, module_name):
"""COMPONENTS OF expansion.
"""
for type_descriptor in type_descriptors:
self.pre_process_components_of_type(type_descriptor,
module_name)
def pre_process_components_of_type(self, type_descriptor, module_name):
if 'members' not in type_descriptor:
return
type_descriptor['members'] = self.pre_process_components_of_expand_members(
type_descriptor['members'],
module_name)
def pre_process_components_of_expand_members(self, members, module_name):
expanded_members = []
for member in members:
if member != EXTENSION_MARKER and 'components-of' in member:
type_descriptor, inner_module_name = self.lookup_type_descriptor(
member['components-of'],
module_name)
inner_members = self.pre_process_components_of_expand_members(
type_descriptor['members'],
inner_module_name)
for inner_member in inner_members:
if inner_member == EXTENSION_MARKER:
break
expanded_members.append(deepcopy(inner_member))
else:
expanded_members.append(member)
return expanded_members
def pre_process_extensibility_implied(self, module, type_descriptors):
"""Make all types extensible.
"""
if not module['extensibility-implied']:
return
for type_descriptor in type_descriptors:
self.pre_process_extensibility_implied_type(type_descriptor)
def pre_process_extensibility_implied_type(self, type_descriptor):
if 'members' not in type_descriptor:
return
members = type_descriptor['members']
for member in members:
if member == EXTENSION_MARKER:
continue
if isinstance(member, list):
for type_descriptor in member:
self.pre_process_extensibility_implied_type(type_descriptor)
else:
self.pre_process_extensibility_implied_type(member)
if EXTENSION_MARKER not in members:
members.append(EXTENSION_MARKER)
def pre_process_tags(self, module, module_name):
"""Add tags where missing.
"""
module_tags = module.get('tags', 'EXPLICIT')
for type_descriptor in module['types'].values():
self.current_type_descriptor = type_descriptor
self.pre_process_tags_type(type_descriptor,
module_tags,
module_name)
def is_dummy_reference(self, type_name):
if 'parameters' not in self.current_type_descriptor:
return False
if type_name in self.current_type_descriptor['parameters']:
return True
return False
def pre_process_tags_type(self,
type_descriptor,
module_tags,
module_name):
type_name = type_descriptor['type']
if 'tag' in type_descriptor:
tag = type_descriptor['tag']
resolved_type_name = self.resolve_type_name(type_name, module_name)
if 'kind' not in tag:
if resolved_type_name == 'CHOICE':
tag['kind'] = 'EXPLICIT'
elif self.is_dummy_reference(type_name):
tag['kind'] = 'EXPLICIT'
elif module_tags in ['IMPLICIT', 'EXPLICIT']:
tag['kind'] = module_tags
else:
tag['kind'] = 'IMPLICIT'
# SEQUENCE, SET and CHOICE.
if 'members' in type_descriptor:
self.pre_process_tags_type_members(type_descriptor,
module_tags,
module_name)
# SEQUENCE OF and SET OF.
if 'element' in type_descriptor:
self.pre_process_tags_type(type_descriptor['element'],
module_tags,
module_name)
def pre_process_tags_type_members(self,
type_descriptor,
module_tags,
module_name):
def is_any_member_tagged(members):
for member in members:
if member == EXTENSION_MARKER:
continue
if 'tag' in member:
return True
return False
number = None
members = flatten(type_descriptor['members'])
# Add tag number to all members if AUTOMATIC TAGS are
# selected and no member is tagged.
if module_tags == 'AUTOMATIC' and not is_any_member_tagged(members):
number = 0
for member in members:
if member == EXTENSION_MARKER:
continue
if number is not None:
if 'tag' not in member:
member['tag'] = {}
member['tag']['number'] = number
number += 1
self.pre_process_tags_type(member,
module_tags,
module_name)
def pre_process_default_value(self, type_descriptors, module_name):
"""SEQUENCE and SET default member value cleanup.
"""
sequences_and_sets = self.get_type_descriptors(
type_descriptors,
['SEQUENCE', 'SET'])
for type_descriptor in sequences_and_sets:
for member in type_descriptor['members']:
if member == EXTENSION_MARKER:
continue
if 'default' not in member:
continue
resolved_member = self.resolve_type_descriptor(member,
module_name)
if resolved_member['type'] == 'BIT STRING':
self.pre_process_default_value_bit_string(member,
resolved_member)
if resolved_member['type'] == 'OCTET STRING':
self.pre_process_default_value_octet_string(member)
if resolved_member['type'] == 'ENUMERATED' and self._numeric_enums:
for key, value in resolved_member['values']:
if key == member['default']:
member['default'] = value
break
def pre_process_default_value_bit_string(self, member, resolved_member):
default = member['default']
if isinstance(default, tuple):
# Already pre-processed.
return
if isinstance(default, list):
named_bits = dict(resolved_member['named-bits'])
reversed_mask = 0
for name in default:
reversed_mask |= (1 << int(named_bits[name]))
mask = int(bin(reversed_mask)[2:][::-1], 2)
number_of_bits = reversed_mask.bit_length()
elif default.startswith('0x'):
if len(default) % 2 == 1:
default += '0'
default = '01' + default[2:]
mask = int(default, 16)
mask >>= lowest_set_bit(mask)
number_of_bits = mask.bit_length() - 1
mask ^= (1 << number_of_bits)
elif default == '0b':
number_of_bits = 0
else:
mask = int(default, 2)
mask >>= lowest_set_bit(mask)
number_of_bits = len(default) - 2
if number_of_bits > 0:
mask = bitstruct.pack('u{}'.format(number_of_bits), mask)
else:
mask = b''
member['default'] = (mask, number_of_bits)
def pre_process_default_value_octet_string(self, member):
default = member['default']
if sys.version_info[0] > 2 and isinstance(default, bytes):
# Already pre-processed.
return
if default.startswith('0b'):
default = default[2:]
if len(default) % 8 != 0:
default += '0' * (-len(default) % 8)
member['default'] = binascii.unhexlify(
hex(int('11111111' + default, 2))[4:]
)
elif default.startswith('0x'):
default = default[2:]
if len(default) % 2 == 1:
default += '0'
member['default'] = binascii.unhexlify(default)
def pre_process_parameterization_step_1(self, types, module_name):
"""X.683 parameterization pre processing - step 1.
"""
for type_name, type_descriptor in types.items():
# Skip if the type is parameterized.
if 'parameters' in type_descriptor:
continue
self.pre_process_parameterization_step_1_type(type_descriptor,
type_name,
module_name)
def pre_process_parameterization_step_1_type(self,
type_descriptor,
type_name,
module_name):
"""Recursively find and replace all parameterized types with their
actual types.
"""
# SEQUENCE, SET and CHOICE.
if 'members' in type_descriptor:
for member in type_descriptor['members']:
if member == EXTENSION_MARKER:
continue
self.pre_process_parameterization_step_1_type(member,
type_name,
module_name)
# SEQUENCE OF and SET OF.
if 'element' in type_descriptor:
self.pre_process_parameterization_step_1_type(
type_descriptor['element'],
type_name,
module_name)
# Just return if the type is not using a parameterized type.
if 'actual-parameters' not in type_descriptor:
return
(parameterized_type_descriptor,
parameterized_module_name) = self.lookup_type_descriptor(
type_descriptor['type'],
module_name)
if 'parameters' not in parameterized_type_descriptor:
raise CompileError(
"Type '{}' in module '{}' is not parameterized.".format(
type_descriptor['type'],
parameterized_module_name))
dummy_parameters = parameterized_type_descriptor['parameters']
actual_parameters = type_descriptor['actual-parameters']
if len(dummy_parameters) != len(actual_parameters):
raise CompileError(
"Parameterized type '{}' in module '{}' takes {} "
"parameters, but {} are given in type '{}' in "
"module '{}'.".format(type_descriptor['type'],
parameterized_module_name,
len(dummy_parameters),
len(actual_parameters),
type_name,
module_name))
parameterized_type_descriptor = deepcopy(parameterized_type_descriptor)
self.pre_process_parameterization_step_1_dummy_to_actual_type(
parameterized_type_descriptor,
dummy_parameters,
actual_parameters,
parameterized_module_name)
self.pre_process_parameterization_step_1_type(
parameterized_type_descriptor,
type_name,
parameterized_module_name)
type_descriptor.update(parameterized_type_descriptor)
if 'module-name' not in type_descriptor:
if module_name != parameterized_module_name:
type_descriptor['module-name'] = parameterized_module_name
if 'parameters' in type_descriptor:
del type_descriptor['parameters']
del type_descriptor['actual-parameters']
def pre_process_parameterization_step_1_dummy_to_actual_type(
self,
type_descriptor,
dummy_parameters,
actual_parameters,
module_name):
if 'members' in type_descriptor:
for member in type_descriptor['members']:
if member == EXTENSION_MARKER:
continue
self.pre_process_parameterization_step_1_dummy_to_actual_type(
member,
dummy_parameters,
actual_parameters,
module_name)
elif 'element' in type_descriptor:
self.pre_process_parameterization_step_1_dummy_to_actual_type(
type_descriptor['element'],
dummy_parameters,
actual_parameters,
module_name)
# Replace dummy with actual in current type descriptor.
for dummy_parameter, actual_parameter in zip(dummy_parameters,
actual_parameters):
if type_descriptor['type'] == dummy_parameter:
type_descriptor.update(actual_parameter)
if 'actual-parameters' in type_descriptor:
for i, parameter in enumerate(type_descriptor['actual-parameters']):
if parameter['type'] == dummy_parameter:
type_descriptor['actual-parameters'][i] = actual_parameter
if 'size' in type_descriptor:
actual_size = []
for item in type_descriptor['size']:
if isinstance(item, tuple):
minimum, maximum = item
if minimum == dummy_parameter:
minimum = actual_parameter
if maximum == dummy_parameter:
maximum = actual_parameter
item = (minimum, maximum)
elif item == dummy_parameter:
item = actual_parameter
actual_size.append(item)
type_descriptor['size'] = actual_size
if 'restricted-to' in type_descriptor:
actual_restricted_to = []
for minimum, maximum in type_descriptor['restricted-to']:
if minimum == dummy_parameter:
minimum = actual_parameter
if maximum == dummy_parameter:
maximum = actual_parameter
actual_restricted_to.append((minimum, maximum))
type_descriptor['restricted-to'] = actual_restricted_to
def pre_process_parameterization_step_2(self, types):
"""X.683 parameterization pre processing - step 2.
"""
# Remove parameterized types as they are no longer needed.
return {
type_name: type_descriptor
for type_name, type_descriptor in types.items()
if 'parameters' not in type_descriptor
}
def resolve_type_name(self, type_name, module_name):
"""Returns the ASN.1 type name of given type.
"""
try:
while True:
if is_object_class_type_name(type_name):
type_name, module_name = self.lookup_object_class_type_name(
type_name,
module_name)
else:
type_descriptor, module_name = self.lookup_type_descriptor(
type_name,
module_name)
type_name = type_descriptor['type']
except CompileError:
pass
return type_name
def resolve_type_descriptor(self, type_descriptor, module_name):
type_name = type_descriptor['type']
try:
while True:
if is_object_class_type_name(type_name):
type_name, module_name = self.lookup_object_class_type_name(
type_name,
module_name)
else:
type_descriptor, module_name = self.lookup_type_descriptor(
type_name,
module_name)
type_name = type_descriptor['type']
except CompileError:
pass
return type_descriptor
def get_type_descriptors(self, type_descriptors, type_names):
result = []
for type_descriptor in type_descriptors:
result += self.get_type_descriptors_type(type_descriptor,
type_names)
return result
def get_type_descriptors_type(self, type_descriptor, type_names):
type_descriptors = []
type_name = type_descriptor['type']
if type_name in type_names:
type_descriptors.append(type_descriptor)
if 'members' in type_descriptor:
for member in type_descriptor['members']:
if member == EXTENSION_MARKER:
continue
if isinstance(member, list):
type_descriptors.extend(self.get_type_descriptors(member,
type_names))
else:
type_descriptors += self.get_type_descriptors_type(member,
type_names)
if 'element' in type_descriptor:
type_descriptors += self.get_type_descriptors_type(
type_descriptor['element'],
type_names)
return type_descriptors
def process_type(self, type_name, type_descriptor, module_name):
return NotImplementedError('To be implemented by subclasses.')
def compile_type(self, name, type_descriptor, module_name):
return NotImplementedError('To be implemented by subclasses.')
def compile_open_types(self, name, type_descriptor, module_name):
"""Compile the open types wrapper for given type. Returns ``None`` if
given type does not have any open types.
"""
compiled = None
type_name = type_descriptor['type']
if type_name in ['SEQUENCE', 'SET']:
compiled_members = []
for member in type_descriptor['members']:
if member == EXTENSION_MARKER:
continue
if isinstance(member, list):
# ToDo: Handle groups.
continue
if is_open_type(member['type']):
if 'table' in member:
table = member['table']
if isinstance(table, list):
compiled_members.append(OpenType(member['name'],
table))
else:
compiled_member = self.compile_open_types(member['name'],
member,
module_name)
if compiled_member is not None:
compiled_members.append(compiled_member)
if compiled_members:
compiled = OpenTypeSequence(name, compiled_members)
elif type_name in ['SEQUENCE OF', 'SET OF']:
compiled_element = self.compile_open_types('',
type_descriptor['element'],
module_name)
if compiled_element:
compiled = OpenTypeSequenceOf(name, compiled_element)
elif type_name == 'CHOICE':
# ToDo: Handle CHOICE.
pass
else:
pass
return compiled
def compile_user_type(self, name, type_name, module_name):
compiled = self.get_compiled_type(name,
type_name,
module_name)
if compiled is None:
self.types_backtrace_push(type_name)
compiled = self.compile_type(
name,
*self.lookup_type_descriptor(
type_name,
module_name))
compiled.type_name = type_name
compiled.module_name = module_name
self.types_backtrace_pop()
self.set_compiled_type(name,
type_name,
module_name,
compiled)
return compiled
def compile_members(self,
members,
module_name,
sort_by_tag=False):
compiled_members = []
has_extension_marker = False
for member in members:
if member == EXTENSION_MARKER:
has_extension_marker = True
continue
if isinstance(member, list):
group_members, _ = self.compile_members(member,
module_name)
compiled_members.extend(group_members)
continue
compiled_member = self.compile_member(member, module_name)
compiled_members.append(compiled_member)
if sort_by_tag:
compiled_members = sorted(compiled_members, key=attrgetter('tag'))
return compiled_members, has_extension_marker
def compile_root_member(self, member, module_name, compiled_members):
compiled_member = self.compile_member(member,
module_name)
compiled_members.append(compiled_member)
def compile_member(self, member, module_name):
if is_object_class_type_name(member['type']):
member, class_module_name = self.convert_object_class_type_descriptor(
member,
module_name)
compiled_member = self.compile_type(member['name'],
member,
class_module_name)
else:
compiled_member = self.compile_type(member['name'],
member,
module_name)
if 'optional' in member:
compiled_member = self.copy(compiled_member)
compiled_member.optional = member['optional']
if 'default' in member:
compiled_member = self.copy(compiled_member)
compiled_member.set_default(member['default'])
if 'size' in member:
compiled_member = self.copy(compiled_member)
compiled_member.set_size_range(*self.get_size_range(member,
module_name))
return compiled_member
def get_size_range(self, type_descriptor, module_name):
"""Returns a tuple of the minimum and maximum values allowed according
the the ASN.1 specification SIZE parameter. Returns (None,
None, None) if the type does not have a SIZE parameter.
"""
size = type_descriptor.get('size', None)
if size is None:
minimum = None
maximum = None
has_extension_marker = None
else:
if isinstance(size[0], tuple):
minimum, maximum = size[0]
else:
minimum = size[0]
maximum = size[0]
has_extension_marker = (EXTENSION_MARKER in size)
if isinstance(minimum, str):
if minimum != 'MIN':
minimum = self.lookup_value(minimum, module_name)[0]['value']
if isinstance(maximum, str):
if maximum != 'MAX':
maximum = self.lookup_value(maximum, module_name)[0]['value']
return minimum, maximum, has_extension_marker
def get_enum_values(self, type_descriptor, module_name):
"""Converts the enum values to ints if they are value references.
"""
enum_values = []
for value in type_descriptor['values']:
if value != EXTENSION_MARKER and not isinstance(value[1], int):
lookup = self.lookup_value(value[1], module_name)
enum_values.append((value[0], lookup[0]['value']))
else:
enum_values.append(value)
return enum_values
def get_restricted_to_range(self, type_descriptor, module_name):
def convert_value(value):
try:
value = float(value)
except ValueError:
if not is_type_name(value):
try:
resolved_type_descriptor = self.resolve_type_descriptor(
type_descriptor,
module_name)
value = resolved_type_descriptor['named-numbers'][value]
except KeyError:
value = self.lookup_value(value,
module_name)[0]['value']
return value
restricted_to = type_descriptor['restricted-to']
if isinstance(restricted_to[0], tuple):
minimum, maximum = restricted_to[0]
else:
minimum = restricted_to[0]
maximum = restricted_to[0]
if isinstance(minimum, str):
minimum = convert_value(minimum)
if isinstance(maximum, str):
maximum = convert_value(maximum)
has_extension_marker = (EXTENSION_MARKER in restricted_to)
return minimum, maximum, has_extension_marker
def get_with_components(self, type_descriptor):
return type_descriptor.get('with-components', None)
def get_named_bits(self, type_descriptor, module_name):
named_bits = type_descriptor.get('named-bits', None)
if named_bits is not None:
named_bit_values = []
for value in named_bits:
if value != EXTENSION_MARKER and not value[1].isdigit():
lookup = self.lookup_value(value[1], module_name)
named_bit_values.append((value[0], lookup[0]['value']))
else:
named_bit_values.append((value[0], int(value[1])))
return named_bit_values
def is_explicit_tag(self, type_descriptor):
try:
return type_descriptor['tag']['kind'] == 'EXPLICIT'
except KeyError:
pass
return False
def get_module_name(self, type_descriptor, module_name):
module_name = type_descriptor.get('module-name', module_name)
try:
_, module_name = self.lookup_type_descriptor(type_descriptor['type'],
module_name)
except CompileError:
pass
return module_name
def lookup_in_modules(self, section, debug_string, name, module_name):
begin_debug_string = debug_string[:1].upper() + debug_string[1:]
module = self._specification[module_name]
if name in module[section]:
return module[section][name], module_name
else:
for from_module_name, imports in module['imports'].items():
if name not in imports:
continue
if from_module_name not in self._specification:
raise CompileError(
"Module '{}' cannot import {} '{}' from missing "
"module '{}'.".format(module_name,
debug_string,
name,
from_module_name))
try:
return self.lookup_in_modules(section,
debug_string,
name,
from_module_name)
except CompileError:
raise CompileError(
"{} '{}' imported by module '{}' not found in "
"module '{}'.".format(
begin_debug_string,
name,
module_name,
from_module_name))
raise CompileError("{} '{}' not found in module '{}'.".format(
begin_debug_string,
name,
module_name))
def lookup_type_descriptor(self, type_name, module_name):
return self.lookup_in_modules('types', 'type', type_name, module_name)
def lookup_value(self, value_name, module_name):
return self.lookup_in_modules('values', 'value', value_name, module_name)
def lookup_object_class_descriptor(self, object_class_name, module_name):
return self.lookup_in_modules('object-classes',
'object class',
object_class_name,
module_name)
def lookup_object_class_type_name(self, type_name, module_name):
class_name, member_name = type_name.split('.')
result = self.lookup_object_class_descriptor(class_name,
module_name)
object_class_descriptor, module_name = result
for member in object_class_descriptor['members']:
if member['name'] == member_name:
return member['type'], module_name
def get_compiled_type(self, name, type_name, module_name):
try:
return self.compiled[module_name][type_name][name]
except KeyError:
return None
def set_compiled_type(self, name, type_name, module_name, compiled):
if module_name not in self.compiled:
self.compiled[module_name] = {}
if type_name not in self.compiled[module_name]:
self.compiled[module_name][type_name] = {}
self.compiled[module_name][type_name][name] = compiled
def convert_object_class_type_descriptor(self, type_descriptor, module_name):
type_name, module_name = self.lookup_object_class_type_name(
type_descriptor['type'],
module_name)
type_descriptor = deepcopy(type_descriptor)
type_descriptor['type'] = type_name
return type_descriptor, module_name
def copy(self, compiled_type):
if not isinstance(compiled_type, Recursive):
compiled_type = copy(compiled_type)
return compiled_type
def set_compiled_restricted_to(self, compiled, type_descriptor, module_name):
compiled = self.copy(compiled)
compiled.set_restricted_to_range(
*self.get_restricted_to_range(type_descriptor,
module_name))
return compiled
def external_type_descriptor(self):
return {
'type': 'SEQUENCE',
'tag': {
'class': 'UNIVERSAL',
'number': 8,
'kind': 'IMPLICIT'
},
'members': [
{
'name': 'direct-reference',
'type': 'OBJECT IDENTIFIER',
'optional': True
},
{
'name': 'indirect-reference',
'type': 'INTEGER',
'optional': True
},
{
'name': 'data-value-descriptor',
'type': 'ObjectDescriptor',
'optional': True
},
{
'name': 'encoding',
'type': 'CHOICE',
'members': [
{
'name': 'single-ASN1-type',
'type': 'NULL', # ToDo: Should be ABSTRACT-SYNTAX.&Type
'tag': {
'number': 0
}
},
{
'name': 'octet-aligned',
'type': 'OCTET STRING',
'tag': {
'number': 1,
'kind': 'IMPLICIT'
}
},
{
'name': 'arbitrary',
'type': 'BIT STRING',
'tag': {
'number': 2,
'kind': 'IMPLICIT'
}
}
]
}
]
}
def enum_values_as_dict(values):
return {
value[1]: value[0]
for value in values
if value != EXTENSION_MARKER
}
def enum_values_split(values):
if EXTENSION_MARKER in values:
index = values.index(EXTENSION_MARKER)
return values[:index], values[index + 1:]
else:
return values, None
def pre_process(specification):
return Compiler(specification).pre_process()
asn1tools-0.169.0/asn1tools/codecs/constraints_checker.py 0000664 0000000 0000000 00000033541 15245442746 0023425 0 ustar 00root root 0000000 0000000 """ASN.1 constraints checker.
"""
import string
from copy import copy
from . import ConstraintsError, ErrorWithLocation
from . import compiler
from . import format_or
from .permitted_alphabet import NUMERIC_STRING
from .permitted_alphabet import PRINTABLE_STRING
from .permitted_alphabet import IA5_STRING
from .permitted_alphabet import BMP_STRING
from .permitted_alphabet import VISIBLE_STRING
STRING_TYPES = [
'OBJECT IDENTIFIER',
'TeletexString',
'NumericString',
'PrintableString',
'IA5String',
'VisibleString',
'GeneralString',
'UTF8String',
'BMPString',
'GraphicString',
'UniversalString',
'ObjectDescriptor'
]
TIME_TYPES = [
'UTCTime',
'GeneralizedTime',
'DATE',
'TIME-OF-DAY',
'DATE-TIME'
]
class Type(object):
def __init__(self, name):
self.name = name
self.minimum = 'MIN'
self.maximum = 'MAX'
def set_range(self, minimum, maximum, has_extension_marker):
if has_extension_marker:
return
if minimum is None:
minimum = 'MIN'
if maximum is None:
maximum = 'MAX'
self.minimum = minimum
self.maximum = maximum
def set_size_range(self, minimum, maximum, has_extension_marker):
self.set_range(minimum, maximum, has_extension_marker)
def set_restricted_to_range(self,
minimum,
maximum,
has_extension_marker):
self.set_range(minimum, maximum, has_extension_marker)
def is_in_range(self, value):
minimum_ok = (not self.has_lower_bound()) or (value >= self.minimum)
maximum_ok = (not self.has_upper_bound()) or (value <= self.maximum)
return minimum_ok and maximum_ok
def set_default(self, value):
pass
def has_lower_bound(self):
return self.minimum != 'MIN'
def has_upper_bound(self):
return self.maximum != 'MAX'
def is_bound(self):
return self.has_lower_bound() and self.has_upper_bound()
def encode(self, data):
raise NotImplementedError('To be implemented by subclasses.')
class String(Type):
PERMITTED_ALPHABET = None
def __init__(self,
name,
permitted_alphabet,
minimum,
maximum,
has_extension_marker):
super(String, self).__init__(name)
self.set_size_range(minimum, maximum, has_extension_marker)
if permitted_alphabet is None:
permitted_alphabet = self.PERMITTED_ALPHABET
self.permitted_alphabet = permitted_alphabet
def encode(self, data):
length = len(data)
if not self.is_in_range(length):
raise ConstraintsError(
'Expected between {} and {} characters, but got {}.'.format(
self.minimum,
self.maximum,
length))
if self.permitted_alphabet is None:
return
for character in data:
if character not in self.permitted_alphabet:
raise ConstraintsError(
"Expected a character in '{}', but got '{}' (0x{:02x}).".format(
''.join([c if c in string.printable[:-5] else '.'
for c in self.permitted_alphabet]),
character if character in string.printable else '.',
ord(character)))
class Boolean(Type):
def encode(self, data):
pass
class Integer(Type):
def __init__(self, name):
super(Integer, self).__init__(name)
def encode(self, data):
if not self.is_in_range(data):
raise ConstraintsError(
'Expected an integer between {} and {}, but got {}.'.format(
self.minimum,
self.maximum,
data))
class Float(Type):
def encode(self, data):
pass
class Null(Type):
def encode(self, data):
pass
class BitString(Type):
def __init__(self, name, minimum, maximum, has_extension_marker):
super(BitString, self).__init__(name)
self.set_size_range(minimum, maximum, has_extension_marker)
def encode(self, data):
number_of_bits = data[1]
if not self.is_in_range(number_of_bits):
raise ConstraintsError(
'Expected between {} and {} bits, but got {}.'.format(
self.minimum,
self.maximum,
number_of_bits))
class Enumerated(Type):
def encode(self, data):
pass
class Bytes(Type):
def __init__(self, name, minimum, maximum, has_extension_marker):
super(Bytes, self).__init__(name)
self.set_size_range(minimum, maximum, has_extension_marker)
def encode(self, data):
length = len(data)
if not self.is_in_range(length):
raise ConstraintsError(
'Expected between {} and {} bytes, but got {}.'.format(
self.minimum,
self.maximum,
length))
class Dict(Type):
def __init__(self, name, members):
super(Dict, self).__init__(name)
self.members = members
def encode(self, data):
for member in self.members:
name = member.name
if name in data:
try:
member.encode(data[name])
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
class List(Type):
def __init__(self, name, element_type, minimum, maximum, has_extension_marker):
super(List, self).__init__(name)
self.element_type = element_type
self.set_size_range(minimum, maximum, has_extension_marker)
def encode(self, data):
length = len(data)
if not self.is_in_range(length):
raise ConstraintsError(
'Expected a list of between {} and {} elements, but got {}.'.format(
self.minimum,
self.maximum,
length))
for entry in data:
self.element_type.encode(entry)
class Choice(Type):
def __init__(self, name, members, has_extension_marker):
super(Choice, self).__init__(name)
self.members = members
self.name_to_member = {member.name: member for member in self.members}
self.has_extension_marker = has_extension_marker
def format_names(self):
return format_or(sorted(self.name_to_member))
def encode(self, data):
value = data[0]
if value in self.name_to_member:
member = self.name_to_member[value]
elif self.has_extension_marker:
return
else:
raise ConstraintsError(
"Expected choice {}, but got '{}'.".format(
self.format_names(),
value))
try:
member.encode(data[1])
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
class NumericString(String):
PERMITTED_ALPHABET = NUMERIC_STRING
class PrintableString(String):
PERMITTED_ALPHABET = PRINTABLE_STRING
class IA5String(String):
PERMITTED_ALPHABET = IA5_STRING
class BMPString(String):
PERMITTED_ALPHABET = BMP_STRING
class VisibleString(String):
PERMITTED_ALPHABET = VISIBLE_STRING
class Time(Type):
def encode(self, data):
pass
class Skip(Type):
def encode(self, data):
pass
class Recursive(compiler.Recursive, Type):
def __init__(self, name, type_name, module_name):
super(Recursive, self).__init__(name)
self.type_name = type_name
self.module_name = module_name
self.inner = None
def set_inner_type(self, inner):
self.inner = copy(inner)
def encode(self, data):
self.inner.encode(data)
class CompiledType(compiler.CompiledType):
def encode(self, data):
try:
self._type.encode(data)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
class Compiler(compiler.Compiler):
def process_type(self, type_name, type_descriptor, module_name):
compiled_type = self.compile_type(type_name,
type_descriptor,
module_name)
return CompiledType(compiled_type)
def compile_type(self, name, type_descriptor, module_name):
module_name = type_descriptor.get('module-name', module_name)
type_name = type_descriptor['type']
if type_name in ['SEQUENCE', 'SET']:
members, _ = self.compile_members(type_descriptor['members'],
module_name)
compiled = Dict(name, members)
elif type_name in ['SEQUENCE OF', 'SET OF']:
element_type = self.compile_type('',
type_descriptor['element'],
module_name)
compiled = List(name,
element_type,
*self.get_size_range(
type_descriptor,
module_name))
elif type_name == 'CHOICE':
compiled = Choice(name,
*self.compile_members(type_descriptor['members'],
module_name))
elif type_name == 'INTEGER':
compiled = Integer(name)
elif type_name == 'REAL':
compiled = Float(name)
elif type_name == 'BOOLEAN':
compiled = Boolean(name)
elif type_name == 'OCTET STRING':
compiled = Bytes(name,
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'ENUMERATED':
compiled = Enumerated(name)
elif type_name in TIME_TYPES:
compiled = Time(name)
elif type_name == 'BIT STRING':
compiled = BitString(name,
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'NumericString':
compiled = NumericString(name,
self.get_permitted_alphabet(type_descriptor),
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'PrintableString':
compiled = PrintableString(name,
self.get_permitted_alphabet(type_descriptor),
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'IA5String':
compiled = IA5String(name,
self.get_permitted_alphabet(type_descriptor),
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'BMPString':
compiled = BMPString(name,
self.get_permitted_alphabet(type_descriptor),
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'VisibleString':
compiled = VisibleString(name,
self.get_permitted_alphabet(type_descriptor),
*self.get_size_range(type_descriptor,
module_name))
elif type_name in STRING_TYPES:
compiled = String(name,
self.get_permitted_alphabet(type_descriptor),
*self.get_size_range(type_descriptor,
module_name))
elif type_name in ['ANY', 'ANY DEFINED BY', 'OpenType']:
compiled = Skip(name)
elif type_name == 'NULL':
compiled = Null(name)
elif type_name == 'EXTERNAL':
members, _ = self.compile_members(
self.external_type_descriptor()['members'],
module_name)
compiled = Dict(name, members)
else:
if type_name in self.types_backtrace:
compiled = Recursive(name,
type_name,
module_name)
self.recursive_types.append(compiled)
else:
compiled = self.compile_user_type(name,
type_name,
module_name)
if 'restricted-to' in type_descriptor:
compiled = self.set_compiled_restricted_to(compiled,
type_descriptor,
module_name)
return compiled
def get_permitted_alphabet(self, type_descriptor):
def char_range(begin, end):
return ''.join([chr(char)
for char in range(ord(begin), ord(end) + 1)])
if 'from' not in type_descriptor:
return
permitted_alphabet = type_descriptor['from']
value = ''
for item in permitted_alphabet:
if isinstance(item, tuple):
value += char_range(item[0], item[1])
else:
value += item
return ''.join(sorted(value))
def compile_dict(specification, numeric_enums=False):
return Compiler(specification, numeric_enums).process()
asn1tools-0.169.0/asn1tools/codecs/der.py 0000664 0000000 0000000 00000031557 15245442746 0020151 0 ustar 00root root 0000000 0000000 """Distinguished Encoding Rules (DER) codec.
"""
from . import ber
from . import restricted_utc_time_to_datetime
from . import restricted_utc_time_from_datetime
from . import restricted_generalized_time_to_datetime
from . import restricted_generalized_time_from_datetime
from .compiler import clean_bit_string_value
from .ber import Class, DecodeTagError, StandardEncodeMixin
from .ber import Encoding
from .ber import Tag
from .ber import encode_length_definite
from .ber import decode_full_length
from .ber import encode_signed_integer
from .ber import Boolean
from .ber import Real
from .ber import Null
from .ber import ObjectIdentifier
from .ber import Enumerated
from .ber import Sequence
from .ber import Set
from .ber import Choice
from .ber import Any
from .ber import AnyDefinedBy
from .ber import Recursive
from .ber import ObjectDescriptor
from .ber import Date
from .ber import TimeOfDay
from .ber import DateTime
# These imports are not used in this module but referenced externally
from .ber import encode_tag
from .ber import encode_real
from .ber import decode_length
from .ber import decode_real
class Type(ber.StandardDecodeMixin, ber.Type):
def set_tag(self, number, flags):
if not Class.APPLICATION & flags:
flags |= Class.CONTEXT_SPECIFIC
super().set_tag(number, flags)
class StringType(StandardEncodeMixin, Type):
TAG = None
ENCODING = None
def __init__(self, name):
super(StringType, self).__init__(name,
self.__class__.__name__,
self.TAG)
def encode_content(self, data, values=None):
return data.encode(self.ENCODING)
def decode_content(self, data, offset, length):
end_offset = offset + length
return data[offset:end_offset].decode(self.ENCODING), end_offset
class ArrayType(StandardEncodeMixin, Type):
def __init__(self, name, tag_name, tag, element_type):
super(ArrayType, self).__init__(name,
tag_name,
tag,
Encoding.CONSTRUCTED)
self.element_type = element_type
def set_tag(self, number, flags):
super(ArrayType, self).set_tag(number,
flags | Encoding.CONSTRUCTED)
def encode_content(self, data, values=None):
encoded_elements = bytearray()
for entry in data:
self.element_type.encode(entry, encoded_elements)
return encoded_elements
def decode_content(self, data, offset, length):
decoded = []
start_offset = offset
while (offset - start_offset) < length:
decoded_element, offset = self.element_type.decode(data, offset)
decoded.append(decoded_element)
return decoded, offset
def __repr__(self):
return '{}({}, {})'.format(self.__class__.__name__,
self.name,
self.element_type)
class Integer(StandardEncodeMixin, Type):
def __init__(self, name):
super(Integer, self).__init__(name,
'INTEGER',
Tag.INTEGER)
def encode_content(self, data, values=None):
return encode_signed_integer(data)
def decode_content(self, data, offset, length):
end_offset = offset + length
return int.from_bytes(data[offset:end_offset], byteorder='big', signed=True), end_offset
class BitString(Type):
def __init__(self, name, has_named_bits):
super(BitString, self).__init__(name,
'BIT STRING',
Tag.BIT_STRING)
self.has_named_bits = has_named_bits
def is_default(self, value):
if self.default is None:
return False
clean_value = clean_bit_string_value(value,
self.has_named_bits)
clean_default = clean_bit_string_value(self.default,
self.has_named_bits)
return clean_value == clean_default
def encode(self, data, encoded, values=None):
number_of_bytes, number_of_rest_bits = divmod(data[1], 8)
data = bytearray(data[0])
if number_of_rest_bits == 0:
data = data[:number_of_bytes]
number_of_unused_bits = 0
else:
last_byte = data[number_of_bytes]
last_byte &= ((0xff >> number_of_rest_bits) ^ 0xff)
data = data[:number_of_bytes]
data.append(last_byte)
number_of_unused_bits = (8 - number_of_rest_bits)
encoded.extend(self.tag)
encoded.extend(encode_length_definite(len(data) + 1))
encoded.append(number_of_unused_bits)
encoded.extend(data)
def decode_content(self, data, offset, length):
end_offset = offset + length
number_of_bits = 8 * (length - 1) - data[offset]
offset += 1
return (bytes(data[offset:end_offset]), number_of_bits), end_offset
class OctetString(StandardEncodeMixin, Type):
def __init__(self, name):
super(OctetString, self).__init__(name,
'OCTET STRING',
Tag.OCTET_STRING)
def encode_content(self, data, values=None):
return data
def decode_content(self, data, offset, length):
end_offset = offset + length
return bytes(data[offset:end_offset]), end_offset
class SequenceOf(ArrayType):
def __init__(self, name, element_type):
super(SequenceOf, self).__init__(name,
'SEQUENCE OF',
Tag.SEQUENCE,
element_type)
class SetOf(ArrayType):
def __init__(self, name, element_type):
super(SetOf, self).__init__(name,
'SET OF',
Tag.SET,
element_type)
class UTF8String(StringType):
TAG = Tag.UTF8_STRING
ENCODING = 'utf-8'
class NumericString(StringType):
TAG = Tag.NUMERIC_STRING
ENCODING = 'ascii'
class PrintableString(StringType):
TAG = Tag.PRINTABLE_STRING
ENCODING = 'ascii'
class IA5String(StringType):
TAG = Tag.IA5_STRING
ENCODING = 'ascii'
class VisibleString(StringType):
TAG = Tag.VISIBLE_STRING
ENCODING = 'ascii'
class GeneralString(StringType):
TAG = Tag.GENERAL_STRING
ENCODING = 'latin-1'
class BMPString(StringType):
TAG = Tag.BMP_STRING
ENCODING = 'utf-16-be'
class UniversalString(StringType):
TAG = Tag.UNIVERSAL_STRING
ENCODING = 'utf-32-be'
class GraphicString(StringType):
TAG = Tag.GRAPHIC_STRING
ENCODING = 'latin-1'
class TeletexString(StringType):
TAG = Tag.T61_STRING
ENCODING = 'iso-8859-1'
class UTCTime(StandardEncodeMixin, Type):
def __init__(self, name):
super(UTCTime, self).__init__(name,
'UTCTime',
Tag.UTC_TIME)
def encode_content(self, data, values=None):
return restricted_utc_time_from_datetime(data).encode('ascii')
def decode_content(self, data, offset, length):
end_offset = offset + length
decoded = data[offset:end_offset].decode('ascii')
return restricted_utc_time_to_datetime(decoded), end_offset
class GeneralizedTime(StandardEncodeMixin, Type):
def __init__(self, name):
super(GeneralizedTime, self).__init__(name,
'GeneralizedTime',
Tag.GENERALIZED_TIME)
def encode_content(self, data, values=None):
return restricted_generalized_time_from_datetime(data).encode('ascii')
def decode_content(self, data, offset, length):
end_offset = offset + length
decoded = data[offset:end_offset].decode('ascii')
return restricted_generalized_time_to_datetime(decoded), end_offset
class Compiler(ber.Compiler):
def compile_implicit_type(self, name, type_descriptor, module_name):
type_name = type_descriptor['type']
if type_name == 'SEQUENCE':
compiled = Sequence(
name,
*self.compile_members(type_descriptor['members'],
module_name))
elif type_name == 'SEQUENCE OF':
compiled = SequenceOf(name,
self.compile_type('',
type_descriptor['element'],
module_name))
elif type_name == 'SET':
compiled = Set(
name,
*self.compile_members(type_descriptor['members'],
module_name))
elif type_name == 'SET OF':
compiled = SetOf(name,
self.compile_type('',
type_descriptor['element'],
module_name))
elif type_name == 'CHOICE':
compiled = Choice(
name,
*self.compile_members(type_descriptor['members'],
module_name))
elif type_name == 'INTEGER':
compiled = Integer(name)
elif type_name == 'REAL':
compiled = Real(name)
elif type_name == 'ENUMERATED':
compiled = Enumerated(name,
self.get_enum_values(type_descriptor,
module_name),
self._numeric_enums)
elif type_name == 'BOOLEAN':
compiled = Boolean(name)
elif type_name == 'OBJECT IDENTIFIER':
compiled = ObjectIdentifier(name)
elif type_name == 'OCTET STRING':
compiled = OctetString(name)
elif type_name == 'TeletexString':
compiled = TeletexString(name)
elif type_name == 'NumericString':
compiled = NumericString(name)
elif type_name == 'PrintableString':
compiled = PrintableString(name)
elif type_name == 'IA5String':
compiled = IA5String(name)
elif type_name == 'VisibleString':
compiled = VisibleString(name)
elif type_name == 'GeneralString':
compiled = GeneralString(name)
elif type_name == 'UTF8String':
compiled = UTF8String(name)
elif type_name == 'BMPString':
compiled = BMPString(name)
elif type_name == 'GraphicString':
compiled = GraphicString(name)
elif type_name == 'UTCTime':
compiled = UTCTime(name)
elif type_name == 'UniversalString':
compiled = UniversalString(name)
elif type_name == 'GeneralizedTime':
compiled = GeneralizedTime(name)
elif type_name == 'DATE':
compiled = Date(name)
elif type_name == 'TIME-OF-DAY':
compiled = TimeOfDay(name)
elif type_name == 'DATE-TIME':
compiled = DateTime(name)
elif type_name == 'BIT STRING':
has_named_bits = ('named-bits' in type_descriptor)
compiled = BitString(name, has_named_bits)
elif type_name == 'ANY':
compiled = Any(name)
elif type_name == 'ANY DEFINED BY':
choices = {}
for key, value in type_descriptor['choices'].items():
choices[key] = self.compile_type(key,
value,
module_name)
compiled = AnyDefinedBy(name,
type_descriptor['value'],
choices)
elif type_name == 'NULL':
compiled = Null(name)
elif type_name == 'EXTERNAL':
compiled = Sequence(
name,
*self.compile_members(self.external_type_descriptor()['members'],
module_name))
compiled.set_tag(Tag.EXTERNAL, 0)
elif type_name == 'ObjectDescriptor':
compiled = ObjectDescriptor(name)
else:
if type_name in self.types_backtrace:
compiled = Recursive(name,
type_name,
module_name)
self.recursive_types.append(compiled)
else:
compiled = self.compile_user_type(name,
type_name,
module_name)
return compiled
def compile_dict(specification, numeric_enums=False):
return Compiler(specification, numeric_enums).process()
asn1tools-0.169.0/asn1tools/codecs/gser.py 0000664 0000000 0000000 00000041150 15245442746 0020325 0 ustar 00root root 0000000 0000000 """General String Encoding Rules (GSER).
"""
import time
import binascii
import math
from copy import copy
import datetime
from . import BaseType, format_bytes, ErrorWithLocation
from . import EncodeError
from . import DecodeError
from . import compiler
from . import format_or
from . import utc_time_from_datetime
from . import generalized_time_from_datetime
from .compiler import enum_values_as_dict
class Type(BaseType):
def encode(self, data, _separator, _indent):
raise NotImplementedError('To be implemented by subclasses.')
def set_size_range(self, minimum, maximum, has_extension_marker):
pass
class MembersType(Type):
def __init__(self, name, members, type_name):
super(MembersType, self).__init__(name, type_name)
self.members = members
def encode(self, data, separator, indent):
encoded_members = []
member_separator = separator + ' ' * indent
for member in self.members:
name = member.name
if name in data:
try:
encoded_member = member.encode(data[name],
member_separator,
indent)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
encoded_member = u'{}{} {}'.format(member_separator,
member.name,
encoded_member)
encoded_members.append(encoded_member)
elif member.optional:
pass
elif not member.has_default():
raise EncodeError(
"{} member '{}' not found in {}.".format(
self.__class__.__name__,
name,
data))
encoded_members = ','.join(encoded_members)
return separator.join(['{' + encoded_members, '}'])
def __repr__(self):
return '{}({}, [{}])'.format(
self.__class__.__name__,
self.name,
', '.join([repr(member) for member in self.members]))
class ArrayType(Type):
def __init__(self, name, type_name, element_type):
super(ArrayType, self).__init__(name, type_name)
self.element_type = element_type
def encode(self, data, separator, indent):
encoded_elements = []
element_separator = separator + ' ' * indent
for entry in data:
encoded_element = self.element_type.encode(entry,
element_separator,
indent)
encoded_element = u'{}{}'.format(element_separator,
encoded_element)
encoded_elements.append(encoded_element)
encoded_elements = ','.join(encoded_elements)
return separator.join(['{' + encoded_elements, '}'])
def __repr__(self):
return '{}({}, {})'.format(self.__class__.__name__,
self.name,
self.element_type)
class Boolean(Type):
def __init__(self, name):
super(Boolean, self).__init__(name, 'BOOLEAN')
def encode(self, data, _separator, _indent):
return 'TRUE' if data else 'FALSE'
class Integer(Type):
def __init__(self, name):
super(Integer, self).__init__(name, 'INTEGER')
def encode(self, data, _separator, _indent):
return str(data)
class Real(Type):
def __init__(self, name):
super(Real, self).__init__(name, 'REAL')
def encode(self, data, _separator, _indent):
if data == float('inf'):
data = 'PLUS-INFINITY'
elif data == float('-inf'):
data = 'MINUS-INFINITY'
elif math.isnan(data):
raise EncodeError('Cannot encode floating point number NaN.')
elif data == 0.0:
data = '0'
else:
data = '{}E0'.format(data)
return data
class Null(Type):
def __init__(self, name):
super(Null, self).__init__(name, 'NULL')
def encode(self, _data, _separator, _indent):
return 'NULL'
class BitString(Type):
def __init__(self, name):
super(BitString, self).__init__(name, 'BIT STRING')
def encode(self, data, _separator, _indent):
encoded = int(binascii.hexlify(data[0]), 16)
encoded |= (0x80 << (8 * len(data[0])))
return "'{}'B".format(bin(encoded)[10:10 + data[1]]).upper()
class OctetString(Type):
def __init__(self, name):
super(OctetString, self).__init__(name, 'OCTET STRING')
def encode(self, data, _separator, _indent):
return "'{}'H".format(format_bytes(data)).upper()
class ObjectIdentifier(Type):
def __init__(self, name):
super(ObjectIdentifier, self).__init__(name, 'OBJECT IDENTIFIER')
def encode(self, data, _separator, _indent):
return data
class Enumerated(Type):
def __init__(self, name, values, numeric):
super(Enumerated, self).__init__(name, 'ENUMERATED')
if numeric:
self.data_to_value = enum_values_as_dict(values)
else:
self.data_to_value = {
v: v for v in enum_values_as_dict(values).values()
}
def encode(self, data, _separator, _indent):
return self.data_to_value[data]
class Sequence(MembersType):
def __init__(self, name, members):
super(Sequence, self).__init__(name, members, 'SEQUENCE')
class SequenceOf(ArrayType):
def __init__(self, name, element_type):
super(SequenceOf, self).__init__(name,
'SEQUENCE OF',
element_type)
class Set(MembersType):
def __init__(self, name, members):
super(Set, self).__init__(name, members, 'SET')
class SetOf(ArrayType):
def __init__(self, name, element_type):
super(SetOf, self).__init__(name,
'SET OF',
element_type)
class Choice(Type):
def __init__(self, name, members):
super(Choice, self).__init__(name, 'CHOICE')
self.members = members
self.name_to_member = {member.name: member for member in self.members}
def format_names(self):
return format_or(sorted([member.name for member in self.members]))
def encode(self, data, separator, indent):
try:
member = self.name_to_member[data[0]]
except KeyError:
raise EncodeError(
"Expected choice {}, but got '{}'.".format(
self.format_names(),
data[0]))
try:
encoded = member.encode(data[1], separator, indent)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
return u'{} : {}'.format(data[0], encoded)
def __repr__(self):
return 'Choice({}, [{}])'.format(
self.name,
', '.join([repr(member) for member in self.members]))
class UTF8String(Type):
def __init__(self, name):
super(UTF8String, self).__init__(name, 'UTF8String')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(data)
class NumericString(Type):
def __init__(self, name):
super(NumericString, self).__init__(name, 'NumericString')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(data)
class PrintableString(Type):
def __init__(self, name):
super(PrintableString, self).__init__(name, 'PrintableString')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(data)
class IA5String(Type):
def __init__(self, name):
super(IA5String, self).__init__(name, 'IA5String')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(data)
class VisibleString(Type):
def __init__(self, name):
super(VisibleString, self).__init__(name, 'VisibleString')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(data)
class GeneralString(Type):
def __init__(self, name):
super(GeneralString, self).__init__(name, 'GeneralString')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(data)
class BMPString(Type):
def __init__(self, name):
super(BMPString, self).__init__(name, 'BMPString')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(data)
class GraphicString(Type):
def __init__(self, name):
super(GraphicString, self).__init__(name, 'GraphicString')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(data)
class UniversalString(Type):
def __init__(self, name):
super(UniversalString, self).__init__(name, 'UniversalString')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(data)
class TeletexString(Type):
def __init__(self, name):
super(TeletexString, self).__init__(name, 'TeletexString')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(data)
class ObjectDescriptor(GraphicString):
pass
class UTCTime(Type):
def __init__(self, name):
super(UTCTime, self).__init__(name, 'UTCTime')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(utc_time_from_datetime(data))
class GeneralizedTime(Type):
def __init__(self, name):
super(GeneralizedTime, self).__init__(name, 'GeneralizedTime')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(generalized_time_from_datetime(data))
class Date(Type):
def __init__(self, name):
super(Date, self).__init__(name, 'DATE')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(str(data))
class TimeOfDay(Type):
def __init__(self, name):
super(TimeOfDay, self).__init__(name, 'TIME-OF-DAY')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(str(data))
class DateTime(Type):
def __init__(self, name):
super(DateTime, self).__init__(name, 'DATE-TIME')
def encode(self, data, _separator, _indent):
return u'"{}"'.format(str(data).replace(' ', 'T'))
class Any(Type):
def __init__(self, name):
super(Any, self).__init__(name, 'ANY')
def encode(self, data, _separator, _indent):
data = format_bytes(data).upper()
return "'{}'H".format(data)
class Recursive(compiler.Recursive, Type):
def __init__(self, name, type_name, module_name):
super(Recursive, self).__init__(name, 'RECURSIVE')
self.type_name = type_name
self.module_name = module_name
self.inner = None
def set_inner_type(self, inner):
self.inner = copy(inner)
def encode(self, data, separator, indent):
return self.inner.encode(data, separator, indent)
class CompiledType(compiler.CompiledType):
def __init__(self, type_name, compiled_type):
super(CompiledType, self).__init__(compiled_type)
self._value_name = type_name.lower()
self._value_type = type_name
def encode(self, data, indent=None):
try:
if indent is None:
encoded = self._type.encode(data, ' ', 0)
else:
encoded = self._type.encode(data, '\n', indent)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
encoded = u'{} {} ::= {}'.format(self._value_name,
self._value_type,
encoded.lstrip(' '))
return encoded.encode('utf-8')
def decode(self, data):
raise NotImplementedError('GSER decoding is not implemented.')
class Compiler(compiler.Compiler):
def process_type(self, type_name, type_descriptor, module_name):
compiled_type = self.compile_type(type_name,
type_descriptor,
module_name)
return CompiledType(type_name, compiled_type)
def compile_type(self, name, type_descriptor, module_name):
module_name = self.get_module_name(type_descriptor, module_name)
type_name = type_descriptor['type']
if type_name == 'SEQUENCE':
members, _ = self.compile_members(
type_descriptor['members'],
module_name)
compiled = Sequence(name, members)
elif type_name == 'SEQUENCE OF':
compiled = SequenceOf(name,
self.compile_type('',
type_descriptor['element'],
module_name))
elif type_name == 'SET':
members, _ = self.compile_members(
type_descriptor['members'],
module_name)
compiled = Set(name, members)
elif type_name == 'SET OF':
compiled = SetOf(name,
self.compile_type('',
type_descriptor['element'],
module_name))
elif type_name == 'CHOICE':
members, _ = self.compile_members(
type_descriptor['members'],
module_name)
compiled = Choice(name, members)
elif type_name == 'INTEGER':
compiled = Integer(name)
elif type_name == 'REAL':
compiled = Real(name)
elif type_name == 'ENUMERATED':
compiled = Enumerated(name,
self.get_enum_values(type_descriptor,
module_name),
self._numeric_enums)
elif type_name == 'BOOLEAN':
compiled = Boolean(name)
elif type_name == 'OBJECT IDENTIFIER':
compiled = ObjectIdentifier(name)
elif type_name == 'OCTET STRING':
compiled = OctetString(name)
elif type_name == 'TeletexString':
compiled = TeletexString(name)
elif type_name == 'NumericString':
compiled = NumericString(name)
elif type_name == 'PrintableString':
compiled = PrintableString(name)
elif type_name == 'IA5String':
compiled = IA5String(name)
elif type_name == 'VisibleString':
compiled = VisibleString(name)
elif type_name == 'GeneralString':
compiled = GeneralString(name)
elif type_name == 'UTF8String':
compiled = UTF8String(name)
elif type_name == 'BMPString':
compiled = BMPString(name)
elif type_name == 'GraphicString':
compiled = GraphicString(name)
elif type_name == 'UTCTime':
compiled = UTCTime(name)
elif type_name == 'UniversalString':
compiled = UniversalString(name)
elif type_name == 'GeneralizedTime':
compiled = GeneralizedTime(name)
elif type_name == 'DATE':
compiled = Date(name)
elif type_name == 'TIME-OF-DAY':
compiled = TimeOfDay(name)
elif type_name == 'DATE-TIME':
compiled = DateTime(name)
elif type_name == 'BIT STRING':
compiled = BitString(name)
elif type_name == 'ANY':
compiled = Any(name)
elif type_name == 'ANY DEFINED BY':
compiled = Any(name)
elif type_name == 'NULL':
compiled = Null(name)
elif type_name == 'EXTERNAL':
members, _ = self.compile_members(
self.external_type_descriptor()['members'],
module_name)
compiled = Sequence(name, members)
elif type_name == 'ObjectDescriptor':
compiled = ObjectDescriptor(name)
else:
if type_name in self.types_backtrace:
compiled = Recursive(name,
type_name,
module_name)
self.recursive_types.append(compiled)
else:
compiled = self.compile_user_type(name,
type_name,
module_name)
return compiled
def compile_dict(specification, numeric_enums=False):
return Compiler(specification, numeric_enums).process()
def decode_full_length(_data):
raise DecodeError('Decode length is not supported for this codec.')
asn1tools-0.169.0/asn1tools/codecs/jer.py 0000664 0000000 0000000 00000042132 15245442746 0020146 0 ustar 00root root 0000000 0000000 """JSON Encoding Rules (JER) codec.
"""
import time
import json
import binascii
import math
import datetime
from ..parser import EXTENSION_MARKER
from . import BaseType, format_bytes, ErrorWithLocation
from . import EncodeError
from . import DecodeError
from . import compiler
from . import format_or
from . import utc_time_to_datetime
from . import utc_time_from_datetime
from . import generalized_time_to_datetime
from . import generalized_time_from_datetime
from .compiler import enum_values_as_dict
class Type(BaseType):
def set_size_range(self, minimum, maximum, has_extension_marker):
pass
class StringType(Type):
def __init__(self, name):
super(StringType, self).__init__(name,
self.__class__.__name__)
def encode(self, data):
return data
def decode(self, data):
return data
class MembersType(Type):
def __init__(self,
name,
members,
type_name):
super(MembersType, self).__init__(name, type_name)
self.members = members
def encode(self, data):
values = {}
for member in self.members:
name = member.name
if name in data:
try:
value = member.encode(data[name])
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
elif member.optional or member.has_default():
continue
else:
raise EncodeError(
"{} member '{}' not found in {}.".format(
self.__class__.__name__,
name,
data))
values[name] = value
return values
def decode(self, data):
values = {}
for member in self.members:
name = member.name
if name in data:
try:
value = member.decode(data[name])
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
values[name] = value
elif member.optional:
pass
elif member.has_default():
values[name] = member.get_default()
return values
def __repr__(self):
return '{}({}, [{}])'.format(
self.__class__.__name__,
self.name,
', '.join([repr(member) for member in self.members]))
class Boolean(Type):
def __init__(self, name):
super(Boolean, self).__init__(name, 'BOOLEAN')
def encode(self, data):
return data
def decode(self, data):
return data
class Integer(Type):
def __init__(self, name):
super(Integer, self).__init__(name, 'INTEGER')
def encode(self, data):
return data
def decode(self, data):
return data
class Real(Type):
def __init__(self, name):
super(Real, self).__init__(name, 'REAL')
def encode(self, data):
if data == float('inf'):
return 'INF'
elif data == float('-inf'):
return '-INF'
elif math.isnan(data):
return 'NaN'
else:
return data
def decode(self, data):
if isinstance(data, float):
return data
else:
return {
'INF': float('inf'),
'-INF': float('-inf'),
'NaN': float('nan'),
'0': 0.0,
'-0': 0.0
}[data]
class Null(Type):
def __init__(self, name):
super(Null, self).__init__(name, 'NULL')
def encode(self, data):
return data
def decode(self, data):
return data
class BitString(Type):
def __init__(self, name, minimum, maximum):
super(BitString, self).__init__(name, 'BIT STRING')
if minimum is None and maximum is None:
self.size = None
elif minimum == maximum:
self.size = minimum
else:
self.size = None
def encode(self, data):
value = format_bytes(data[0]).upper()
if self.size is None:
value = {
"value": value,
"length": data[1]
}
return value
def decode(self, data):
if self.size is None:
return (binascii.unhexlify(data['value']), data['length'])
else:
return (binascii.unhexlify(data), self.size)
class OctetString(Type):
def __init__(self, name):
super(OctetString, self).__init__(name, 'OCTET STRING')
def encode(self, data):
return format_bytes(data).upper()
def decode(self, data):
return binascii.unhexlify(data)
class ObjectIdentifier(Type):
def __init__(self, name):
super(ObjectIdentifier, self).__init__(name, 'OBJECT IDENTIFIER')
def encode(self, data):
return data
def decode(self, data):
return str(data)
class Enumerated(Type):
def __init__(self, name, values, numeric):
super(Enumerated, self).__init__(name, 'ENUMERATED')
if numeric:
self.values = {k: k for k in enum_values_as_dict(values)}
else:
self.values = {
v: v for v in enum_values_as_dict(values).values()
}
self.has_extension_marker = (EXTENSION_MARKER in values)
def format_values(self):
return format_or(sorted(list(self.values)))
def encode(self, data):
try:
value = self.values[data]
except KeyError:
raise EncodeError(
"Expected enumeration value {}, but got '{}'.".format(
self.format_values(),
data))
return value
def decode(self, data):
if data in self.values:
return self.values[data]
elif self.has_extension_marker:
return None
else:
raise DecodeError(
"Expected enumeration value {}, but got '{}'.".format(
self.format_values(),
data))
class Sequence(MembersType):
def __init__(self, name, members):
super(Sequence, self).__init__(name, members, 'SEQUENCE')
class SequenceOf(Type):
def __init__(self, name, element_type):
super(SequenceOf, self).__init__(name, 'SEQUENCE OF')
self.element_type = element_type
def encode(self, data):
values = []
for entry in data:
value = self.element_type.encode(entry)
values.append(value)
return values
def decode(self, data):
values = []
for element_data in data:
value = self.element_type.decode(element_data)
values.append(value)
return values
def __repr__(self):
return 'SequenceOf({}, {})'.format(self.name,
self.element_type)
class Set(MembersType):
def __init__(self, name, members):
super(Set, self).__init__(name, members, 'SET')
class SetOf(Type):
def __init__(self, name, element_type):
super(SetOf, self).__init__(name, 'SET OF')
self.element_type = element_type
def encode(self, data):
values = []
for entry in data:
value = self.element_type.encode(entry)
values.append(value)
return values
def decode(self, data):
values = []
for element_data in data:
value = self.element_type.decode(element_data)
values.append(value)
return values
def __repr__(self):
return 'SetOf({}, {})'.format(self.name,
self.element_type)
class Choice(Type):
def __init__(self, name, members, has_extension_marker):
super(Choice, self).__init__(name, 'CHOICE')
self.members = members
self.name_to_member = {member.name: member for member in self.members}
self.has_extension_marker = has_extension_marker
def format_names(self):
return format_or(sorted([member.name for member in self.members]))
def encode(self, data):
try:
member = self.name_to_member[data[0]]
except KeyError:
raise EncodeError(
"Expected choice {}, but got '{}'.".format(
self.format_names(),
data[0]))
try:
return {member.name: member.encode(data[1])}
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
def decode(self, data):
name, value = list(data.items())[0]
if name in self.name_to_member:
member = self.name_to_member[name]
elif self.has_extension_marker:
return (None, None)
else:
raise DecodeError(
"Expected choice {}, but got '{}'.".format(
self.format_names(),
name))
try:
return (name, member.decode(value))
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
def __repr__(self):
return 'Choice({}, [{}])'.format(
self.name,
', '.join([repr(member) for member in self.members]))
class UTF8String(StringType):
pass
class NumericString(StringType):
pass
class PrintableString(StringType):
pass
class IA5String(StringType):
pass
class VisibleString(StringType):
pass
class GeneralString(StringType):
pass
class BMPString(StringType):
pass
class GraphicString(StringType):
pass
class UniversalString(StringType):
pass
class TeletexString(StringType):
pass
class ObjectDescriptor(GraphicString):
pass
class UTCTime(StringType):
def encode(self, data):
return utc_time_from_datetime(data)
def decode(self, data):
return utc_time_to_datetime(data)
class GeneralizedTime(StringType):
def encode(self, data):
return generalized_time_from_datetime(data)
def decode(self, data):
return generalized_time_to_datetime(data)
class Date(StringType):
def encode(self, data):
return str(data)
def decode(self, data):
return datetime.date(*time.strptime(data, '%Y-%m-%d')[:3])
class TimeOfDay(StringType):
def encode(self, data):
return str(data)
def decode(self, data):
return datetime.time(*time.strptime(data, '%H:%M:%S')[3:6])
class DateTime(StringType):
def encode(self, data):
return str(data).replace(' ', 'T')
def decode(self, data):
return datetime.datetime(*time.strptime(data, '%Y-%m-%dT%H:%M:%S')[:6])
class Any(Type):
def __init__(self, name):
super(Any, self).__init__(name, 'ANY')
def encode(self, _data):
raise NotImplementedError('ANY is not yet implemented.')
def decode(self, _data):
raise NotImplementedError('ANY is not yet implemented.')
class Recursive(compiler.Recursive, Type):
def __init__(self, name, type_name, module_name):
super(Recursive, self).__init__(name, 'RECURSIVE')
self.type_name = type_name
self.module_name = module_name
self._inner = None
def set_inner_type(self, inner):
self._inner = inner
def encode(self, data):
return self._inner.encode(data)
def decode(self, data):
return self._inner.decode(data)
class CompiledType(compiler.CompiledType):
def encode(self, data, indent=None):
try:
dictionary = self._type.encode(data)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
if indent is None:
string = json.dumps(dictionary, separators=(',', ':'))
else:
string = json.dumps(dictionary, indent=indent)
return string.encode('utf-8')
def decode(self, data):
try:
return self._type.decode(json.loads(data.decode('utf-8')))
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
class Compiler(compiler.Compiler):
def process_type(self, type_name, type_descriptor, module_name):
compiled_type = self.compile_type(type_name,
type_descriptor,
module_name)
return CompiledType(compiled_type)
def compile_type(self, name, type_descriptor, module_name):
module_name = self.get_module_name(type_descriptor, module_name)
type_name = type_descriptor['type']
if type_name == 'SEQUENCE':
members, _ = self.compile_members(
type_descriptor['members'],
module_name)
compiled = Sequence(name, members)
elif type_name == 'SEQUENCE OF':
compiled = SequenceOf(name,
self.compile_type('',
type_descriptor['element'],
module_name))
elif type_name == 'SET':
members, _ = self.compile_members(
type_descriptor['members'],
module_name)
compiled = Set(name, members)
elif type_name == 'SET OF':
compiled = SetOf(name,
self.compile_type('',
type_descriptor['element'],
module_name))
elif type_name == 'CHOICE':
compiled = Choice(name,
*self.compile_members(
type_descriptor['members'],
module_name))
elif type_name == 'INTEGER':
compiled = Integer(name)
elif type_name == 'REAL':
compiled = Real(name)
elif type_name == 'ENUMERATED':
compiled = Enumerated(name,
self.get_enum_values(type_descriptor,
module_name),
self._numeric_enums)
elif type_name == 'BOOLEAN':
compiled = Boolean(name)
elif type_name == 'OBJECT IDENTIFIER':
compiled = ObjectIdentifier(name)
elif type_name == 'OCTET STRING':
compiled = OctetString(name)
elif type_name == 'TeletexString':
compiled = TeletexString(name)
elif type_name == 'NumericString':
compiled = NumericString(name)
elif type_name == 'PrintableString':
compiled = PrintableString(name)
elif type_name == 'IA5String':
compiled = IA5String(name)
elif type_name == 'VisibleString':
compiled = VisibleString(name)
elif type_name == 'GeneralString':
compiled = GeneralString(name)
elif type_name == 'DATE':
compiled = Date(name)
elif type_name == 'TIME-OF-DAY':
compiled = TimeOfDay(name)
elif type_name == 'DATE-TIME':
compiled = DateTime(name)
elif type_name == 'UTF8String':
compiled = UTF8String(name)
elif type_name == 'BMPString':
compiled = BMPString(name)
elif type_name == 'GraphicString':
compiled = GraphicString(name)
elif type_name == 'UTCTime':
compiled = UTCTime(name)
elif type_name == 'UniversalString':
compiled = UniversalString(name)
elif type_name == 'GeneralizedTime':
compiled = GeneralizedTime(name)
elif type_name == 'BIT STRING':
minimum, maximum, _ = self.get_size_range(type_descriptor,
module_name)
compiled = BitString(name, minimum, maximum)
elif type_name == 'ANY':
compiled = Any(name)
elif type_name == 'ANY DEFINED BY':
compiled = Any(name)
elif type_name == 'NULL':
compiled = Null(name)
elif type_name == 'EXTERNAL':
members, _ = self.compile_members(
self.external_type_descriptor()['members'],
module_name)
compiled = Sequence(name, members)
elif type_name == 'ObjectDescriptor':
compiled = ObjectDescriptor(name)
else:
if type_name in self.types_backtrace:
compiled = Recursive(name,
type_name,
module_name)
self.recursive_types.append(compiled)
else:
compiled = self.compile_user_type(name,
type_name,
module_name)
return compiled
def compile_dict(specification, numeric_enums=False):
return Compiler(specification, numeric_enums).process()
def decode_full_length(_data):
raise DecodeError('Decode length is not supported for this codec.')
asn1tools-0.169.0/asn1tools/codecs/oer.py 0000664 0000000 0000000 00000134556 15245442746 0020167 0 ustar 00root root 0000000 0000000 """Basic Octet Encoding Rules (OER) codec.
"""
import binascii
from copy import copy
import struct
from operator import attrgetter
import datetime
from ..parser import EXTENSION_MARKER
from . import BaseType, format_bytes, ErrorWithLocation
from . import EncodeError
from . import DecodeError
from . import OutOfDataError
from . import format_or
from . import compiler
from . import utc_time_to_datetime
from . import utc_time_from_datetime
from . import generalized_time_to_datetime
from . import generalized_time_from_datetime
from .compiler import enum_values_as_dict
from .ber import Class
from .ber import Tag
from .ber import encode_object_identifier
from .ber import decode_object_identifier
from . import der
def encode_tag(number, flags):
if number < 63:
tag = bytearray([flags | number])
else:
tag = bytearray([flags | 0x3f])
encoded = bytearray()
while number > 0:
encoded.append(0x80 | (number & 0x7f))
number >>= 7
encoded[0] &= 0x7f
encoded.reverse()
tag.extend(encoded)
return bytes(tag)
class Encoder(object):
def __init__(self):
self.number_of_bits = 0
self.value = 0
def __iadd__(self, other):
self.append_non_negative_binary_integer(other.value,
other.number_of_bits)
return self
def number_of_bytes(self):
return (self.number_of_bits + 7) // 8
def set_bit(self, offset):
self.value |= (1 << (self.number_of_bits - offset - 1))
def align(self):
width = (8 * self.number_of_bytes() - self.number_of_bits)
self.number_of_bits += width
self.value <<= width
def append_bit(self, bit):
"""Append given bit.
"""
self.number_of_bits += 1
self.value <<= 1
self.value |= bit
def append_bits(self, data, number_of_bits):
"""Append given bits.
"""
if number_of_bits == 0:
return
value = int(binascii.hexlify(data), 16)
value >>= (8 * len(data) - number_of_bits)
self.append_non_negative_binary_integer(value, number_of_bits)
def append_u8(self, value):
return self.append_non_negative_binary_integer(value, 8)
def append_bytes(self, data):
"""Append given data.
"""
self.append_bits(data, 8 * len(data))
def as_bytearray(self):
"""Return the bits as a bytearray.
"""
if self.number_of_bits == 0:
return bytearray()
data = self.value
data |= (0x80 << self.number_of_bits)
data = hex(data)[4:].rstrip('L')
return bytearray(binascii.unhexlify(data))
def append_length_determinant(self, value):
if value < 128:
self.append_non_negative_binary_integer(value, 8)
else:
encoded = bytearray()
while value > 0:
encoded.append(value & 0xff)
value >>= 8
length = len(encoded)
if length > 127:
raise EncodeError('Length determinant {} is too big.'.format(value))
self.append_u8(0x80 | length)
self.append_bytes(encoded[::-1])
def append_non_negative_binary_integer(self, value, number_of_bits):
"""Append given integer value.
"""
self.number_of_bits += number_of_bits
self.value <<= number_of_bits
self.value |= value
def append_integer(self, value):
number_of_bits = value.bit_length()
if value < 0:
number_of_bytes = ((number_of_bits + 7) // 8)
value = ((1 << (8 * number_of_bytes)) + value)
if (value & (1 << (8 * number_of_bytes - 1))) == 0:
value |= (0xff << (8 * number_of_bytes))
number_of_bytes += 1
elif value > 0:
number_of_bytes = ((number_of_bits + 7) // 8)
if number_of_bits == (8 * number_of_bytes):
number_of_bytes += 1
else:
number_of_bytes = 1
self.append_length_determinant(number_of_bytes)
self.append_non_negative_binary_integer(value, 8 * number_of_bytes)
def append_unsigned_integer(self, value):
number_of_bits = max(value.bit_length(), 1)
number_of_bytes = ((number_of_bits + 7) // 8)
self.append_length_determinant(number_of_bytes)
self.append_non_negative_binary_integer(value, 8 * number_of_bytes)
def __repr__(self):
return format_bytes(self.as_bytearray())
class Decoder(object):
def __init__(self, encoded):
self.number_of_bits = (8 * len(encoded))
self.total_number_of_bits = self.number_of_bits
if len(encoded) > 0:
self.value = int(binascii.hexlify(encoded), 16)
else:
self.value = 0
def align(self):
width = (self.number_of_bits & 0x7)
self.number_of_bits -= width
def number_of_read_bits(self):
return self.total_number_of_bits - self.number_of_bits
def skip_bits(self, number_of_bits):
if number_of_bits > self.number_of_bits:
raise OutOfDataError(self.number_of_read_bits())
self.number_of_bits -= number_of_bits
def peek_bit(self):
return ((self.value >> (self.number_of_bits - 1)) & 1)
def clear_bit(self):
self.value &= (1 << (self.number_of_bits - 1)) - 1
def read_bit(self):
"""Read a bit.
"""
if self.number_of_bits == 0:
raise OutOfDataError(self.number_of_read_bits())
self.number_of_bits -= 1
return ((self.value >> self.number_of_bits) & 1)
def read_bits(self, number_of_bits):
"""Read given number of bits.
"""
if number_of_bits > self.number_of_bits:
raise OutOfDataError(self.number_of_read_bits())
self.number_of_bits -= number_of_bits
mask = ((1 << number_of_bits) - 1)
value = ((self.value >> self.number_of_bits) & mask)
value &= mask
value |= (0x80 << number_of_bits)
return binascii.unhexlify(hex(value)[4:].rstrip('L'))
def read_byte(self):
return self.read_non_negative_binary_integer(8)
def read_bytes(self, number_of_bytes):
return self.read_bits(8 * number_of_bytes)
def read_non_negative_binary_integer(self, number_of_bits):
"""Read an integer value of given number of bits.
"""
if number_of_bits > self.number_of_bits:
raise OutOfDataError(self.number_of_read_bits())
self.number_of_bits -= number_of_bits
mask = ((1 << number_of_bits) - 1)
return ((self.value >> self.number_of_bits) & mask)
def read_length_determinant(self):
value = self.read_byte()
if value & 0x80:
length = (value & 0x7f)
value = self.read_non_negative_binary_integer(8 * length)
return value
def read_integer(self):
number_of_bytes = self.read_length_determinant()
number_of_bits = 8 * number_of_bytes
value = self.read_non_negative_binary_integer(number_of_bits)
if value & (1 << (number_of_bits - 1)):
value -= (1 << number_of_bits) - 1
value -= 1
return value
def read_unsigned_integer(self):
number_of_bytes = self.read_length_determinant()
number_of_bits = 8 * number_of_bytes
return self.read_non_negative_binary_integer(number_of_bits)
def read_tag(self):
byte = self.read_byte()
tag = bytearray([byte])
if byte & 0x3f == 0x3f:
while True:
byte = self.read_byte()
tag.append(byte)
if byte & 0x80 == 0:
break
return bytes(tag)
class Type(BaseType):
def __init__(self, name, type_name, number, flags=0):
super().__init__(name, type_name)
self.module_name = None
if number is None:
self.tag = None
else:
self.tag = encode_tag(number, flags)
def set_tag(self, number, flags):
if not Class.APPLICATION & flags:
flags |= Class.CONTEXT_SPECIFIC
self.tag = encode_tag(number, flags)
def set_size_range(self, minimum, maximum, has_extension_marker):
pass
def set_restricted_to_range(self, minimum, maximum, has_extension_marker):
pass
class KnownMultiplierStringType(Type):
TAG = None
ENCODING = None
def __init__(self,
name,
minimum=None,
maximum=None,
has_extension_marker=False):
super(KnownMultiplierStringType, self).__init__(name,
self.__class__.__name__,
self.TAG)
self.number_of_bytes = None
if minimum is not None or maximum is not None:
if not has_extension_marker:
if minimum == maximum:
self.number_of_bytes = minimum
def encode(self, data, encoder):
encoded = data.encode(self.ENCODING)
if self.number_of_bytes is None:
encoder.append_length_determinant(len(encoded))
encoder.append_bytes(encoded)
else:
encoder.append_bytes(encoded)
def decode(self, decoder):
if self.number_of_bytes is None:
number_of_bytes = decoder.read_length_determinant()
else:
number_of_bytes = self.number_of_bytes
return decoder.read_bytes(number_of_bytes).decode(self.ENCODING)
class MembersType(Type):
def __init__(self, name, type_name, tag, root_members, additions):
super(MembersType, self).__init__(name,
type_name,
tag)
self.root_members = root_members
self.additions = additions
self.optionals = [
member
for member in root_members
if member.optional or member.default is not None
]
def encode(self, data, encoder):
if self.additions is not None:
offset = encoder.number_of_bits
encoder.append_bit(0)
self.encode_root(data, encoder)
if len(self.additions) > 0:
if self.encode_additions(data, encoder):
encoder.set_bit(offset)
else:
self.encode_root(data, encoder)
def encode_root(self, data, encoder):
for optional in self.optionals:
if optional.optional:
encoder.append_bit(optional.name in data)
elif optional.name in data:
encoder.append_bit(not optional.is_default(data[optional.name]))
else:
encoder.append_bit(0)
encoder.align()
for member in self.root_members:
self.encode_member(member, data, encoder)
def encode_additions(self, data, encoder):
# Encode extension additions.
presence_bits = 0
addition_encoders = []
try:
for addition in self.additions:
presence_bits <<= 1
addition_encoder = Encoder()
self.encode_member(addition,
data,
addition_encoder,
encode_default=True)
if addition_encoder.number_of_bits > 0 or addition.name in data:
addition_encoders.append(addition_encoder)
presence_bits |= 1
except EncodeError:
pass
# Return false if no extension additions are present.
if not addition_encoders:
return False
# Presence bit field.
number_of_additions = len(self.additions)
number_of_unused_bits = (8 - (number_of_additions % 8))
encoder.append_length_determinant(((number_of_additions + 7) // 8) + 1)
encoder.append_non_negative_binary_integer(number_of_unused_bits, 8)
encoder.append_non_negative_binary_integer(presence_bits,
number_of_additions)
encoder.align()
for addition_encoder in addition_encoders:
encoder.append_length_determinant(addition_encoder.number_of_bytes())
encoder += addition_encoder
return True
def encode_member(self, member, data, encoder, encode_default=False):
name = member.name
if name in data:
try:
if member.default is None:
member.encode(data[name], encoder)
elif not member.is_default(data[name]) or encode_default:
member.encode(data[name], encoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
elif member.optional or member.has_default():
pass
else:
raise EncodeError(
"{} member '{}' not found in {}.".format(
self.__class__.__name__,
name,
data))
def decode(self, decoder):
if self.additions is not None:
if decoder.read_bit():
decoded = self.decode_root(decoder)
decoded.update(self.decode_additions(decoder))
return decoded
else:
return self.decode_root(decoder)
else:
return self.decode_root(decoder)
def decode_root(self, decoder):
values = {}
optionals = {
optional: decoder.read_bit()
for optional in self.optionals
}
decoder.align()
for member in self.root_members:
if optionals.get(member, True):
try:
value = member.decode(decoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
values[member.name] = value
elif member.has_default():
values[member.name] = member.default
return values
def decode_additions(self, decoder):
# Presence bit field.
length = decoder.read_length_determinant()
unused_bits = decoder.read_byte()
num_additions = ((length - 1) * 8) - unused_bits
presence_bits = decoder.read_non_negative_binary_integer(num_additions)
decoder.align()
decoded = {}
for i in range(num_additions):
if presence_bits & (1 << (num_additions - i - 1)):
member_length = decoder.read_length_determinant()
if i < len(self.additions):
addition = self.additions[i]
try:
decoded[addition.name] = addition.decode(decoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(addition)
raise e
else:
decoder.skip_bits(8 * member_length)
return decoded
def __repr__(self):
return '{}({}, [{}])'.format(
self.__class__.__name__,
self.name,
', '.join([repr(member) for member in self.root_members]))
class ArrayType(Type):
def __init__(self, name, type_name, tag, element_type):
super(ArrayType, self).__init__(name,
type_name,
tag)
self.element_type = element_type
def encode(self, data, encoder):
encoder.append_unsigned_integer(len(data))
for entry in data:
self.element_type.encode(entry, encoder)
def decode(self, decoder):
length = decoder.read_unsigned_integer()
decoded = []
for _ in range(length):
decoded_element = self.element_type.decode(decoder)
decoded.append(decoded_element)
return decoded
def __repr__(self):
return '{}({}, {})'.format(self.__class__.__name__,
self.name,
self.element_type)
class Boolean(Type):
def __init__(self, name):
super(Boolean, self).__init__(name,
'BOOLEAN',
Tag.BOOLEAN)
def encode(self, data, encoder):
encoder.append_non_negative_binary_integer(0xff * data, 8)
def decode(self, decoder):
return bool(decoder.read_byte())
class Integer(Type):
def __init__(self, name):
super(Integer, self).__init__(name,
'INTEGER',
Tag.INTEGER)
self.has_extension_marker = False
self.length = None
self.fmt = None
self.signed = True
def set_restricted_to_range(self, minimum, maximum, has_extension_marker):
self.has_extension_marker = has_extension_marker
if minimum != 'MIN':
self.signed = (minimum < 0)
if minimum == 'MIN' or maximum == 'MAX' or has_extension_marker:
return
if minimum >= 0:
if maximum < 256:
self.length = 1
self.fmt = '>B'
elif maximum < 65536:
self.length = 2
self.fmt = '>H'
elif maximum < 4294967296:
self.length = 4
self.fmt = '>I'
elif maximum < 18446744073709551616:
self.length = 8
self.fmt = '>Q'
elif minimum >= -128 and maximum < 128:
self.length = 1
self.fmt = '>b'
elif minimum >= -32768 and maximum < 32768:
self.length = 2
self.fmt = '>h'
elif minimum >= -2147483648 and maximum < 2147483648:
self.length = 4
self.fmt = '>i'
elif minimum >= -9223372036854775808 and maximum < 9223372036854775808:
self.length = 8
self.fmt = '>q'
def encode(self, data, encoder):
if self.fmt:
encoder.append_bytes(struct.pack(self.fmt, data))
elif self.signed:
encoder.append_integer(data)
else:
encoder.append_unsigned_integer(data)
def decode(self, decoder):
if self.fmt:
return struct.unpack(self.fmt, decoder.read_bytes(self.length))[0]
elif self.signed:
return decoder.read_integer()
else:
return decoder.read_unsigned_integer()
class Real(Type):
def __init__(self, name, with_components):
super(Real, self).__init__(name, 'REAL', Tag.REAL)
if with_components is None:
self.length = None
self.fmt = None
else:
mantissa, base, exponent = self.unpack_with_components(with_components)
if all([mantissa, base, exponent]):
if self.is_binary32(mantissa, base, exponent):
self.length = 4
self.fmt = '>f'
elif self.is_binary64(mantissa, base, exponent):
self.length = 8
self.fmt = '>d'
else:
self.length = None
self.fmt = None
else:
self.length = None
self.fmt = None
def unpack_with_components(self, with_components):
with_components = dict(with_components)
try:
mantissa = with_components['mantissa']
base = with_components['base']
exponent = with_components['exponent']
except KeyError:
mantissa = None
base = None
exponent = None
return (mantissa, base, exponent)
def is_binary32(self, mantissa, base, exponent):
return (-16777215 <= mantissa[0] <= mantissa[1] <= 16777215
and base == 2
and -149 <= exponent[0] <= exponent[1] <= 104)
def is_binary64(self, mantissa, base, exponent):
return (-9007199254740991 <= mantissa[0] <= mantissa[1] <= 9007199254740991
and base == 2
and -1074 <= exponent[0] <= exponent[1] <= 971)
def encode(self, data, encoder):
if self.fmt is None:
encoded = der.encode_real(data)
encoder.append_length_determinant(len(encoded))
encoder.append_bytes(encoded)
else:
try:
encoder.append_bytes(struct.pack(self.fmt, data))
except (struct.error, OverflowError):
raise EncodeError(
'Expected an IEEE 754 {} bits floating point number, but '
'got {}.'.format(8 * self.length,
data))
def decode(self, decoder):
if self.fmt is None:
length = decoder.read_length_determinant()
return der.decode_real(bytearray(decoder.read_bytes(length)))
else:
return struct.unpack(self.fmt, decoder.read_bytes(self.length))[0]
class Null(Type):
def __init__(self, name):
super(Null, self).__init__(name, 'NULL', Tag.NULL)
def encode(self, _data, _encoder):
return
def decode(self, _decoder):
return
class BitString(Type):
def __init__(self, name, named_bits, minimum, maximum, has_extension_marker):
super(BitString, self).__init__(name,
'BIT STRING',
Tag.BIT_STRING)
self.number_of_bits = None
self.named_bits = named_bits
if minimum is not None or maximum is not None:
if not has_extension_marker:
if minimum == maximum:
self.number_of_bits = minimum
def encode(self, data, encoder):
number_of_bytes, number_of_rest_bits = divmod(data[1], 8)
data = bytearray(data[0])
if number_of_rest_bits == 0:
data = data[:number_of_bytes]
number_of_unused_bits = 0
else:
last_byte = data[number_of_bytes]
last_byte &= ((0xff >> number_of_rest_bits) ^ 0xff)
data = data[:number_of_bytes]
data.append(last_byte)
number_of_unused_bits = (8 - number_of_rest_bits)
number_of_bytes += 1
if self.number_of_bits is None:
encoder.append_length_determinant(number_of_bytes + 1)
encoder.append_non_negative_binary_integer(number_of_unused_bits,
8)
encoder.append_bytes(data)
else:
encoder.append_bytes(data)
def decode(self, decoder):
if self.number_of_bits is None:
number_of_bytes = decoder.read_length_determinant()
number_of_unused_bits = decoder.read_byte()
number_of_bytes -= 1
number_of_bits = (8 * number_of_bytes - number_of_unused_bits)
else:
number_of_bytes = (self.number_of_bits + 7) // 8
number_of_bits = self.number_of_bits
return (decoder.read_bytes(number_of_bytes), number_of_bits)
class OctetString(Type):
def __init__(self, name, minimum, maximum, has_extension_marker):
super(OctetString, self).__init__(name,
'OCTET STRING',
Tag.OCTET_STRING)
self.number_of_bytes = None
self.set_size_range(minimum, maximum, has_extension_marker)
def set_size_range(self, minimum, maximum, has_extension_marker):
if minimum is not None or maximum is not None:
if not has_extension_marker:
if minimum == maximum:
self.number_of_bytes = minimum
def encode(self, data, encoder):
if self.number_of_bytes is None:
encoder.append_length_determinant(len(data))
encoder.append_bytes(data)
else:
encoder.append_bytes(data)
def decode(self, decoder):
if self.number_of_bytes is None:
number_of_bytes = decoder.read_length_determinant()
else:
number_of_bytes = self.number_of_bytes
return decoder.read_bytes(number_of_bytes)
class ObjectIdentifier(Type):
def __init__(self, name):
super(ObjectIdentifier, self).__init__(name,
'OBJECT IDENTIFIER',
Tag.OBJECT_IDENTIFIER)
def encode(self, data, encoder):
encoded_subidentifiers = encode_object_identifier(data)
encoder.append_length_determinant(len(encoded_subidentifiers))
encoder.append_bytes(bytearray(encoded_subidentifiers))
def decode(self, decoder):
length = decoder.read_length_determinant()
data = decoder.read_bytes(length)
return decode_object_identifier(bytearray(data), 0, len(data))
class Enumerated(Type):
def __init__(self, name, values, numeric):
super(Enumerated, self).__init__(name,
'ENUMERATED',
Tag.ENUMERATED)
if numeric:
self.value_to_data = {k: k for k in enum_values_as_dict(values)}
self.data_to_value = self.value_to_data
else:
self.value_to_data = enum_values_as_dict(values)
self.data_to_value = {v: k for k, v in self.value_to_data.items()}
self.has_extension_marker = (EXTENSION_MARKER in values)
def format_names(self):
return format_or(sorted(list(self.value_to_data.values())))
def format_values(self):
return format_or(sorted(list(self.value_to_data)))
def encode(self, data, encoder):
try:
value = self.data_to_value[data]
except KeyError:
raise EncodeError(
"Expected enumeration value {}, but got '{}'.".format(
self.format_names(),
data))
if 0 <= value <= 127:
encoder.append_non_negative_binary_integer(value, 8)
else:
offset = encoder.number_of_bits
encoder.append_integer(value)
encoder.set_bit(offset)
def decode(self, decoder):
if decoder.peek_bit():
decoder.clear_bit()
value = decoder.read_integer()
else:
value = decoder.read_byte()
if value in self.value_to_data:
return self.value_to_data[value]
elif self.has_extension_marker:
return None
else:
raise DecodeError(
'Expected enumeration value {}, but got {}.'.format(
self.format_values(), value))
class Sequence(MembersType):
def __init__(self, name, root_members, additions):
super(Sequence, self).__init__(name,
'SEQUENCE',
Tag.SEQUENCE,
root_members,
additions)
class SequenceOf(ArrayType):
def __init__(self, name, element_type):
super(SequenceOf, self).__init__(name,
'SEQUENCE OF',
Tag.SEQUENCE,
element_type)
class Set(MembersType):
def __init__(self, name, root_members, additions):
super(Set, self).__init__(name,
'SET',
Tag.SET,
root_members,
additions)
class SetOf(ArrayType):
def __init__(self, name, element_type):
super(SetOf, self).__init__(name,
'SET OF',
Tag.SET,
element_type)
class Choice(Type):
def __init__(self, name, root_members, additions):
super(Choice, self).__init__(name, 'CHOICE', None)
self.root_members = root_members
self.name_to_root_member = {
member.name: member for member in root_members
}
self.tag_to_root_member = {}
self.add_tags(self.tag_to_root_member, root_members)
if additions is None:
additions = []
self.has_extension_marker = False
else:
self.has_extension_marker = True
self.additions = additions
self.name_to_addition = {
member.name: member for member in additions
}
self.tag_to_addition = {}
self.add_tags(self.tag_to_addition, additions)
@property
def members(self):
return self.root_members + self.additions
def add_tags(self, tag_to_member, members):
for member in members:
tag_to_member[member.tag] = member
def format_tags(self):
return format_or(
sorted([format_bytes(member.tag) for member in self.members]))
def format_names(self):
return format_or(sorted([member.name for member in self.members]))
def encode(self, data, encoder):
name = data[0]
if name in self.name_to_root_member:
member = self.name_to_root_member[name]
encoder.append_bytes(member.tag)
try:
member.encode(data[1], encoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
elif name in self.name_to_addition:
member = self.name_to_addition[name]
encoder.append_bytes(member.tag)
addition_encoder = Encoder()
try:
member.encode(data[1], addition_encoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
encoder.append_length_determinant(addition_encoder.number_of_bytes())
encoder += addition_encoder
else:
raise EncodeError(
"Expected choice {}, but got '{}'.".format(
self.format_names(),
data[0]))
# def encode_member(self, member, data, encoder):
# try:
# member.encode(data, encoder)
# except EncodeError as e:
# e.location.append(member.name)
# raise
def decode(self, decoder):
tag = decoder.read_tag()
if tag in self.tag_to_root_member:
member = self.tag_to_root_member[tag]
try:
decoded = member.decode(decoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
elif tag in self.tag_to_addition:
member = self.tag_to_addition[tag]
decoder.read_length_determinant()
try:
decoded = member.decode(decoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
elif self.has_extension_marker:
length = decoder.read_length_determinant()
decoder.skip_bits(8 * length)
return (None, None)
else:
raise DecodeError(
"Expected choice member tag {}, but got '{}'.".format(
self.format_tags(), format_bytes(tag)))
return (member.name, decoded)
def __repr__(self):
return 'Choice({}, [{}])'.format(
self.name,
', '.join([repr(member) for member in self.members]))
class UTF8String(KnownMultiplierStringType):
TAG = Tag.UTF8_STRING
ENCODING = 'utf-8'
class NumericString(KnownMultiplierStringType):
TAG = Tag.NUMERIC_STRING
ENCODING = 'ascii'
class PrintableString(KnownMultiplierStringType):
TAG = Tag.PRINTABLE_STRING
ENCODING = 'ascii'
class IA5String(KnownMultiplierStringType):
TAG = Tag.IA5_STRING
ENCODING = 'ascii'
class VisibleString(KnownMultiplierStringType):
TAG = Tag.VISIBLE_STRING
ENCODING = 'ascii'
class GeneralString(KnownMultiplierStringType):
TAG = Tag.GENERAL_STRING
ENCODING = 'latin-1'
class BMPString(KnownMultiplierStringType):
TAG = Tag.BMP_STRING
ENCODING = 'utf-16-be'
class GraphicString(KnownMultiplierStringType):
TAG = Tag.GENERAL_STRING
ENCODING = 'latin-1'
class UniversalString(KnownMultiplierStringType):
TAG = Tag.UNIVERSAL_STRING
ENCODING = 'utf-32-be'
class TeletexString(KnownMultiplierStringType):
TAG = Tag.T61_STRING
ENCODING = 'iso-8859-1'
class ObjectDescriptor(GraphicString):
TAG = Tag.OBJECT_DESCRIPTOR
class UTCTime(VisibleString):
TAG = Tag.UTC_TIME
def encode(self, data, encoder):
encoded = utc_time_from_datetime(data)
return super(UTCTime, self).encode(encoded, encoder)
def decode(self, decoder):
decoded = super(UTCTime, self).decode(decoder)
return utc_time_to_datetime(decoded)
class GeneralizedTime(VisibleString):
TAG = Tag.GENERALIZED_TIME
def encode(self, data, encoder):
encoded = generalized_time_from_datetime(data)
return super(GeneralizedTime, self).encode(encoded, encoder)
def decode(self, decoder):
decoded = super(GeneralizedTime, self).decode(decoder)
return generalized_time_to_datetime(decoded)
class Date(Type):
def __init__(self, name):
super(Date, self).__init__(name, 'DATE', None)
year = Integer('year')
month = Integer('month')
day = Integer('day')
month.set_restricted_to_range(1, 12, False)
day.set_restricted_to_range(1, 31, False)
self._inner = Sequence('DATE-ENCODING',
[year, month, day],
None)
def encode(self, data, encoder):
data = {
'year': data.year,
'month': data.month,
'day': data.day
}
self._inner.encode(data, encoder)
def decode(self, decoder):
decoded = self._inner.decode(decoder)
return datetime.date(decoded['year'],
decoded['month'],
decoded['day'])
class TimeOfDay(Type):
def __init__(self, name):
super(TimeOfDay, self).__init__(name, 'TIME-OF-DAY', None)
hours = Integer('hours')
minutes = Integer('minutes')
seconds = Integer('seconds')
hours.set_restricted_to_range(0, 24, False)
minutes.set_restricted_to_range(0, 59, False)
seconds.set_restricted_to_range(0, 60, False)
self._inner = Sequence('TIME-OF-DAY-ENCODING',
[hours, minutes, seconds],
None)
def encode(self, data, encoder):
data = {
'hours': data.hour,
'minutes': data.minute,
'seconds': data.second
}
self._inner.encode(data, encoder)
def decode(self, decoder):
decoded = self._inner.decode(decoder)
return datetime.time(decoded['hours'],
decoded['minutes'],
decoded['seconds'])
class DateTime(Type):
def __init__(self, name):
super(DateTime, self).__init__(name, 'DATE-TIME', None)
self._date = Date('date')
self._time = TimeOfDay('time')
def encode(self, data, encoder):
self._date.encode(data, encoder)
self._time.encode(data, encoder)
def decode(self, decoder):
decoded_date = self._date.decode(decoder)
decoded_time = self._time.decode(decoder)
return datetime.datetime(decoded_date.year,
decoded_date.month,
decoded_date.day,
decoded_time.hour,
decoded_time.minute,
decoded_time.second)
class Any(Type):
def __init__(self, name):
super(Any, self).__init__(name, 'ANY', None)
def encode(self, data, encoder):
raise NotImplementedError('ANY is not yet implemented.')
def decode(self, decoder):
raise NotImplementedError('ANY is not yet implemented.')
class AnyDefinedBy(Type):
def __init__(self, name, type_member, choices):
super(AnyDefinedBy, self).__init__(name,
'ANY DEFINED BY',
None,
None)
self.type_member = type_member
self.choices = choices
def encode(self, data, encoder):
raise NotImplementedError('ANY DEFINED BY is not yet implemented.')
def decode(self, decoder):
raise NotImplementedError('ANY DEFINED BY is not yet implemented.')
class Recursive(compiler.Recursive, Type):
def __init__(self, name, type_name, module_name):
super(Recursive, self).__init__(name, 'RECURSIVE', None)
self.type_name = type_name
self.module_name = module_name
self.tag_number = None
self.tag_flags = None
self.inner = None
def set_inner_type(self, inner):
self.inner = copy(inner)
if self.tag_number is not None:
self.inner.set_tag(self.tag_number, self.tag_flags)
def encode(self, data, encoder):
self.inner.encode(data, encoder)
def decode(self, decoder):
return self.inner.decode(decoder)
class CompiledType(compiler.CompiledType):
def encode(self, data):
encoder = Encoder()
try:
self._type.encode(data, encoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
return encoder.as_bytearray()
def decode(self, data):
decoder = Decoder(bytearray(data))
try:
return self._type.decode(decoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
class Compiler(compiler.Compiler):
def process_type(self, type_name, type_descriptor, module_name):
compiled_type = self.compile_type(type_name,
type_descriptor,
module_name)
return CompiledType(compiled_type)
def compile_type(self, name, type_descriptor, module_name):
module_name = self.get_module_name(type_descriptor, module_name)
type_name = type_descriptor['type']
if type_name == 'SEQUENCE':
compiled = Sequence(name,
*self.compile_members(type_descriptor['members'],
module_name))
elif type_name == 'SEQUENCE OF':
compiled = SequenceOf(name,
self.compile_type('',
type_descriptor['element'],
module_name))
elif type_name == 'SET':
compiled = Set(name,
*self.compile_members(type_descriptor['members'],
module_name,
sort_by_tag=True))
elif type_name == 'SET OF':
compiled = SetOf(name,
self.compile_type('',
type_descriptor['element'],
module_name))
elif type_name == 'CHOICE':
compiled = Choice(
name,
*self.compile_members(type_descriptor['members'],
module_name))
elif type_name == 'INTEGER':
compiled = Integer(name)
elif type_name == 'REAL':
compiled = Real(name, self.get_with_components(type_descriptor))
elif type_name == 'ENUMERATED':
compiled = Enumerated(name,
self.get_enum_values(type_descriptor,
module_name),
self._numeric_enums)
elif type_name == 'BOOLEAN':
compiled = Boolean(name)
elif type_name == 'OBJECT IDENTIFIER':
compiled = ObjectIdentifier(name)
elif type_name == 'OCTET STRING':
compiled = OctetString(name,
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'TeletexString':
compiled = TeletexString(name)
elif type_name == 'NumericString':
compiled = NumericString(name,
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'PrintableString':
compiled = PrintableString(name,
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'IA5String':
compiled = IA5String(name,
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'VisibleString':
compiled = VisibleString(name,
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'GeneralString':
compiled = GeneralString(name)
elif type_name == 'UTF8String':
compiled = UTF8String(name,
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'BMPString':
compiled = BMPString(name)
elif type_name == 'GraphicString':
compiled = GraphicString(name)
elif type_name == 'UTCTime':
compiled = UTCTime(name)
elif type_name == 'UniversalString':
compiled = UniversalString(name)
elif type_name == 'GeneralizedTime':
compiled = GeneralizedTime(name)
elif type_name == 'DATE':
compiled = Date(name)
elif type_name == 'TIME-OF-DAY':
compiled = TimeOfDay(name)
elif type_name == 'DATE-TIME':
compiled = DateTime(name)
elif type_name == 'BIT STRING':
compiled = BitString(name,
self.get_named_bits(type_descriptor,
module_name),
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'ANY':
compiled = Any(name)
elif type_name == 'ANY DEFINED BY':
choices = {}
for key, value in type_descriptor['choices'].items():
choices[key] = self.compile_type(key,
value,
module_name)
compiled = AnyDefinedBy(name,
type_descriptor['value'],
choices)
elif type_name == 'NULL':
compiled = Null(name)
elif type_name == 'EXTERNAL':
compiled = Sequence(
name,
*self.compile_members(self.external_type_descriptor()['members'],
module_name))
compiled.set_tag(Tag.EXTERNAL, 0)
elif type_name == 'ObjectDescriptor':
compiled = ObjectDescriptor(name)
else:
if type_name in self.types_backtrace:
compiled = Recursive(name,
type_name,
module_name)
self.recursive_types.append(compiled)
else:
compiled = self.compile_user_type(name,
type_name,
module_name)
if 'tag' in type_descriptor:
compiled = self.copy(compiled)
tag = type_descriptor['tag']
class_ = tag.get('class', None)
if class_ == 'APPLICATION':
flags = Class.APPLICATION
elif class_ == 'PRIVATE':
flags = Class.PRIVATE
else:
flags = 0
compiled.set_tag(tag['number'], flags)
if 'restricted-to' in type_descriptor:
compiled = self.set_compiled_restricted_to(compiled,
type_descriptor,
module_name)
return compiled
def compile_members(self,
members,
module_name,
sort_by_tag=False):
compiled_members = []
in_extension = False
additions = None
for member in members:
if member == EXTENSION_MARKER:
in_extension = not in_extension
if in_extension:
additions = []
elif in_extension:
self.compile_extension_member(member,
module_name,
additions)
else:
self.compile_root_member(member,
module_name,
compiled_members)
if sort_by_tag:
compiled_members = sorted(compiled_members, key=attrgetter('tag'))
return compiled_members, additions
def compile_extension_member(self,
member,
module_name,
additions):
if isinstance(member, list):
for memb in member:
compiled_member = self.compile_member(memb,
module_name)
additions.append(compiled_member)
else:
compiled_member = self.compile_member(member,
module_name)
additions.append(compiled_member)
def compile_dict(specification, numeric_enums=False):
return Compiler(specification, numeric_enums).process()
def decode_full_length(_data):
raise DecodeError('Decode length is not supported for this codec.')
asn1tools-0.169.0/asn1tools/codecs/per.py 0000664 0000000 0000000 00000220675 15245442746 0020166 0 ustar 00root root 0000000 0000000 """Aligned Packed Encoding Rules (PER) codec.
"""
from operator import attrgetter
from operator import itemgetter
import binascii
import string
import datetime
from ..parser import EXTENSION_MARKER
from . import BaseType, format_bytes, ErrorWithLocation
from . import EncodeError
from . import DecodeError
from . import OutOfDataError
from . import compiler
from . import format_or
from . import restricted_utc_time_to_datetime
from . import restricted_utc_time_from_datetime
from . import restricted_generalized_time_to_datetime
from . import restricted_generalized_time_from_datetime
from .compiler import enum_values_split
from .compiler import enum_values_as_dict
from .compiler import clean_bit_string_value
from .compiler import rstrip_bit_string_zeros
from .ber import encode_real
from .ber import decode_real
from .ber import encode_object_identifier
from .ber import decode_object_identifier
from .permitted_alphabet import NUMERIC_STRING
from .permitted_alphabet import PRINTABLE_STRING
from .permitted_alphabet import IA5_STRING
from .permitted_alphabet import BMP_STRING
from .permitted_alphabet import VISIBLE_STRING
def is_unbound(minimum, maximum):
return ((minimum in [None, 'MIN'])
or (maximum in [None, 'MAX'])
or (maximum > 65535))
def to_int(chars):
if isinstance(chars, int):
return chars
num = 0
byte_array = bytearray(chars)
while len(byte_array) > 0:
num <<= 8
byte = byte_array.pop(0)
num += byte
return num
def to_byte_array(num, number_of_bits):
byte_array = bytearray()
while number_of_bits > 0:
byte_array.insert(0, (num & 0xff))
num >>= 8
number_of_bits -= 8
return byte_array
def integer_as_number_of_bits(size):
"""Returns the minimum number of bits needed to fit given positive
integer.
"""
if size == 0:
return 0
else:
return size.bit_length()
def integer_as_number_of_bits_power_of_two(size):
"""Returns the minimum power of two number of bits needed to fit given
positive integer.
"""
if size == 0:
return 0
else:
bit_length = integer_as_number_of_bits(size)
bit_length_pow_2 = 1
while bit_length > bit_length_pow_2:
bit_length_pow_2 <<= 1
return bit_length_pow_2
def size_as_number_of_bytes(size):
"""Returns the minimum number of bytes needed to fit given positive
integer.
"""
if size == 0:
return 1
else:
number_of_bits = size.bit_length()
rest = (number_of_bits % 8)
if rest != 0:
number_of_bits += (8 - rest)
return number_of_bits // 8
CLASS_PRIO = {
'UNIVERSAL': 0,
'APPLICATION': 1,
'CONTEXT_SPECIFIC': 2,
'PRIVATE': 3
}
class PermittedAlphabet(object):
def __init__(self, encode_map, decode_map):
self.encode_map = encode_map
self.decode_map = decode_map
def __len__(self):
return len(self.encode_map)
def encode(self, value):
try:
return self.encode_map[value]
except KeyError:
raise EncodeError(
"Expected a character in '{}', but got '{}' (0x{:02x})'.".format(
''.join(sorted([chr(v) for v in self.encode_map])),
chr(value) if chr(value) in string.printable else '.',
value))
def decode(self, value):
try:
return self.decode_map[value]
except KeyError:
raise DecodeError(
"Expected a value in {}, but got {:d}.".format(
list(self.decode_map), value))
class Encoder(object):
def __init__(self):
self.number_of_bits = 0
self.value = 0
self.chunks_number_of_bits = 0
self.chunks = []
def __iadd__(self, other):
for value, number_of_bits in other.chunks:
self.append_non_negative_binary_integer(value, number_of_bits)
self.append_non_negative_binary_integer(other.value,
other.number_of_bits)
return self
def reset(self):
self.number_of_bits = 0
self.value = 0
self.chunks_number_of_bits = 0
self.chunks = []
def are_all_bits_zero(self):
return not (any([value for value, _ in self.chunks]) or self.value)
def number_of_bytes(self):
return (self.chunks_number_of_bits + self.number_of_bits + 7) // 8
def offset(self):
return (len(self.chunks), self.number_of_bits)
def set_bit(self, offset):
chunk_offset, bit_offset = offset
if len(self.chunks) == chunk_offset:
self.value |= (1 << (self.number_of_bits - bit_offset - 1))
else:
chunk = self.chunks[chunk_offset]
chunk[0] |= (1 << (chunk[1] - bit_offset - 1))
def align(self):
self.align_always()
def align_always(self):
width = 8 * self.number_of_bytes()
width -= self.chunks_number_of_bits
width -= self.number_of_bits
self.number_of_bits += width
self.value <<= width
def append_bit(self, bit):
"""Append given bit.
"""
self.number_of_bits += 1
self.value <<= 1
self.value |= bit
def append_bits(self, data, number_of_bits):
"""Append given bits.
"""
if number_of_bits == 0:
return
value = int(binascii.hexlify(data), 16)
value >>= (8 * len(data) - number_of_bits)
self.append_non_negative_binary_integer(value, number_of_bits)
def append_non_negative_binary_integer(self, value, number_of_bits):
"""Append given integer value.
"""
if self.number_of_bits > 4096:
self.chunks.append([self.value, self.number_of_bits])
self.chunks_number_of_bits += self.number_of_bits
self.number_of_bits = 0
self.value = 0
self.number_of_bits += number_of_bits
self.value <<= number_of_bits
self.value |= value
def append_bytes(self, data):
"""Append given data.
"""
self.append_bits(data, 8 * len(data))
def as_bytearray(self):
"""Return the bits as a bytearray.
"""
value = 0
number_of_bits = 0
for chunk_value, chunk_number_of_bits in self.chunks:
value <<= chunk_number_of_bits
value |= chunk_value
number_of_bits += chunk_number_of_bits
value <<= self.number_of_bits
value |= self.value
number_of_bits += self.number_of_bits
if number_of_bits == 0:
return bytearray()
number_of_alignment_bits = (8 - (number_of_bits % 8))
if number_of_alignment_bits != 8:
value <<= number_of_alignment_bits
number_of_bits += number_of_alignment_bits
value |= (0x80 << number_of_bits)
value = hex(value)[4:].rstrip('L')
return bytearray(binascii.unhexlify(value))
def append_length_determinant(self, length):
if length < 128:
encoded = bytearray([length])
elif length < 16384:
encoded = bytearray([(0x80 | (length >> 8)), (length & 0xff)])
elif length < 32768:
encoded = b'\xc1'
length = 16384
elif length < 49152:
encoded = b'\xc2'
length = 32768
elif length < 65536:
encoded = b'\xc3'
length = 49152
else:
encoded = b'\xc4'
length = 65536
self.append_bytes(encoded)
return length
def append_length_determinant_chunks(self, length):
offset = 0
chunk_length = length
while True:
chunk_length = self.append_length_determinant(chunk_length)
yield offset, chunk_length
if chunk_length < 16384:
break
offset += chunk_length
chunk_length = length - offset
def append_normally_small_non_negative_whole_number(self, value):
if value < 64:
self.append_non_negative_binary_integer(value, 7)
else:
self.append_bit(1)
length = (value.bit_length() + 7) // 8
self.append_length_determinant(length)
self.append_non_negative_binary_integer(value, 8 * length)
def append_normally_small_length(self, value):
if value <= 64:
self.append_non_negative_binary_integer(value - 1, 7)
elif value <= 127:
self.append_non_negative_binary_integer(0x100 | value, 9)
else:
raise NotImplementedError(
'Normally small length number >127 is not yet supported.')
def append_constrained_whole_number(self,
value,
minimum,
maximum,
number_of_bits):
_range = (maximum - minimum + 1)
value -= minimum
if _range <= 255:
self.append_non_negative_binary_integer(value, number_of_bits)
elif _range == 256:
self.align_always()
self.append_non_negative_binary_integer(value, 8)
elif _range <= 65536:
self.align_always()
self.append_non_negative_binary_integer(value, 16)
else:
self.align_always()
self.append_non_negative_binary_integer(value, number_of_bits)
def append_unconstrained_whole_number(self, value):
number_of_bits = value.bit_length()
if value < 0:
number_of_bytes = ((number_of_bits + 7) // 8)
value = ((1 << (8 * number_of_bytes)) + value)
if (value & (1 << (8 * number_of_bytes - 1))) == 0:
value |= (0xff << (8 * number_of_bytes))
number_of_bytes += 1
elif value > 0:
number_of_bytes = ((number_of_bits + 7) // 8)
if number_of_bits == (8 * number_of_bytes):
number_of_bytes += 1
else:
number_of_bytes = 1
self.append_length_determinant(number_of_bytes)
self.append_non_negative_binary_integer(value,
8 * number_of_bytes)
def __repr__(self):
return format_bytes(self.as_bytearray())
class Decoder(object):
def __init__(self, encoded):
self.number_of_bits = (8 * len(encoded))
self.total_number_of_bits = self.number_of_bits
if len(encoded) > 0:
value = int(binascii.hexlify(encoded), 16)
value |= (0x80 << self.number_of_bits)
self.value = bin(value)[10:]
else:
self.value = ''
def align(self):
self.align_always()
def align_always(self):
width = (self.number_of_bits & 0x7)
self.number_of_bits -= width
def number_of_read_bits(self):
return self.total_number_of_bits - self.number_of_bits
def skip_bits(self, number_of_bits):
if number_of_bits > self.number_of_bits:
raise OutOfDataError(self.number_of_read_bits())
self.number_of_bits -= number_of_bits
def read_bit(self):
"""Read a bit.
"""
if self.number_of_bits == 0:
raise OutOfDataError(self.number_of_read_bits())
bit = int(self.value[self.number_of_read_bits()])
self.number_of_bits -= 1
return bit
def read_bits(self, number_of_bits):
"""Read given number of bits.
"""
if number_of_bits > self.number_of_bits:
raise OutOfDataError(self.number_of_read_bits())
offset = self.number_of_read_bits()
value = self.value[offset:offset + number_of_bits]
self.number_of_bits -= number_of_bits
value = '10000000' + value
number_of_alignment_bits = (8 - (number_of_bits % 8))
if number_of_alignment_bits != 8:
value += '0' * number_of_alignment_bits
return binascii.unhexlify(hex(int(value, 2))[4:].rstrip('L'))
def read_bytes(self, number_of_bytes):
return self.read_bits(8 * number_of_bytes)
def read_non_negative_binary_integer(self, number_of_bits):
"""Read an integer value of given number of bits.
"""
if number_of_bits > self.number_of_bits:
raise OutOfDataError(self.number_of_read_bits())
if number_of_bits == 0:
return 0
offset = self.number_of_read_bits()
value = self.value[offset:offset + number_of_bits]
self.number_of_bits -= number_of_bits
return int(value, 2)
def read_length_determinant(self):
value = self.read_non_negative_binary_integer(8)
if (value & 0x80) == 0x00:
return value
elif (value & 0xc0) == 0x80:
return (((value & 0x7f) << 8)
| (self.read_non_negative_binary_integer(8)))
else:
try:
return {
0xc1: 16384,
0xc2: 32768,
0xc3: 49152,
0xc4: 65536
}[value]
except KeyError:
raise DecodeError(
'Bad length determinant fragmentation value 0x{:02x}.'.format(
value))
def read_length_determinant_chunks(self):
while True:
length = self.read_length_determinant()
yield length
if length < 16384:
break
def read_normally_small_non_negative_whole_number(self):
if not self.read_bit():
decoded = self.read_non_negative_binary_integer(6)
else:
length = self.read_length_determinant()
decoded = self.read_non_negative_binary_integer(8 * length)
return decoded
def read_normally_small_length(self):
if not self.read_bit():
return self.read_non_negative_binary_integer(6) + 1
elif not self.read_bit():
return self.read_non_negative_binary_integer(7)
else:
raise NotImplementedError(
'Normally small length number >64 is not yet supported.')
def read_constrained_whole_number(self,
minimum,
maximum,
number_of_bits):
_range = (maximum - minimum + 1)
if _range <= 255:
value = self.read_non_negative_binary_integer(number_of_bits)
elif _range == 256:
self.align_always()
value = self.read_non_negative_binary_integer(8)
elif _range <= 65536:
self.align_always()
value = self.read_non_negative_binary_integer(16)
else:
self.align_always()
value = self.read_non_negative_binary_integer(number_of_bits)
return value + minimum
def read_unconstrained_whole_number(self):
length = self.read_length_determinant()
decoded = self.read_non_negative_binary_integer(8 * length)
number_of_bits = (8 * length)
if decoded & (1 << (number_of_bits - 1)):
mask = ((1 << number_of_bits) - 1)
decoded = (decoded - mask)
decoded -= 1
return decoded
class Type(BaseType):
def __init__(self, name, type_name):
super().__init__(name, type_name)
self.module_name = None
self.tag = None
def set_size_range(self, minimum, maximum, has_extension_marker):
pass
def set_restricted_to_range(self, minimum, maximum, has_extension_marker):
pass
class KnownMultiplierStringType(Type):
ENCODING = 'ascii'
PERMITTED_ALPHABET = PermittedAlphabet({}, {})
def __init__(self,
name,
minimum=None,
maximum=None,
has_extension_marker=False,
permitted_alphabet=None):
super(KnownMultiplierStringType, self).__init__(name,
self.__class__.__name__)
self.set_size_range(minimum, maximum, has_extension_marker)
if permitted_alphabet is None:
permitted_alphabet = self.PERMITTED_ALPHABET
self.permitted_alphabet = permitted_alphabet
self.bits_per_character = integer_as_number_of_bits_power_of_two(
len(permitted_alphabet) - 1)
if len(self.PERMITTED_ALPHABET) < 2 ** self.bits_per_character:
self.permitted_alphabet = self.PERMITTED_ALPHABET
def set_size_range(self, minimum, maximum, has_extension_marker):
self.minimum = minimum
self.maximum = maximum
self.has_extension_marker = has_extension_marker
if is_unbound(minimum, maximum):
self.number_of_bits = None
else:
size = maximum - minimum
self.number_of_bits = integer_as_number_of_bits(size)
def encode(self, data, encoder):
if self.has_extension_marker:
if self.minimum <= len(data) <= self.maximum:
encoder.append_bit(0)
else:
raise NotImplementedError(
'String size extension is not yet implemented.')
if self.number_of_bits is None:
return self.encode_unbound(data, encoder)
elif self.minimum != self.maximum:
encoder.append_constrained_whole_number(len(data),
self.minimum,
self.maximum,
self.number_of_bits)
if self.maximum > 1 and len(data) > 0:
encoder.align()
elif self.maximum * self.bits_per_character > 16:
encoder.align()
for value in data:
encoder.append_non_negative_binary_integer(
self.permitted_alphabet.encode(
to_int(value.encode(self.ENCODING))),
self.bits_per_character)
def encode_unbound(self, data, encoder):
encoder.align()
for offset, length in encoder.append_length_determinant_chunks(len(data)):
for entry in data[offset:offset + length]:
encoder.append_non_negative_binary_integer(
self.permitted_alphabet.encode(
to_int(entry.encode(self.ENCODING))),
self.bits_per_character)
def decode(self, decoder):
if self.has_extension_marker:
bit = decoder.read_bit()
if bit:
raise NotImplementedError(
'String size extension is not yet implemented.')
if self.number_of_bits is None:
return self.decode_unbound(decoder)
else:
if self.minimum != self.maximum:
length = decoder.read_constrained_whole_number(self.minimum,
self.maximum,
self.number_of_bits)
if self.maximum > 1 and length > 0:
decoder.align()
elif self.maximum * self.bits_per_character > 16:
decoder.align()
length = self.minimum
else:
length = self.minimum
data = bytearray()
for _ in range(length):
value = decoder.read_non_negative_binary_integer(self.bits_per_character)
value = self.permitted_alphabet.decode(value)
data += to_byte_array(value, self.bits_per_character)
return data.decode(self.ENCODING)
def decode_unbound(self, decoder):
decoder.align()
decoded = bytearray()
orig_bits_per_character = integer_as_number_of_bits_power_of_two(
len(self.ALPHABET) - 1)
for length in decoder.read_length_determinant_chunks():
for _ in range(length):
value = decoder.read_non_negative_binary_integer(
self.bits_per_character)
value = self.permitted_alphabet.decode(value)
decoded += to_byte_array(value, orig_bits_per_character)
return decoded.decode(self.ENCODING)
class StringType(Type):
ENCODING = None
LENGTH_MULTIPLIER = 1
def __init__(self, name):
super(StringType, self).__init__(name, self.__class__.__name__)
def encode(self, data, encoder):
encoded = data.encode(self.ENCODING)
encoder.align()
for offset, length in encoder.append_length_determinant_chunks(len(data)):
offset *= self.LENGTH_MULTIPLIER
data = encoded[offset:offset + self.LENGTH_MULTIPLIER * length]
encoder.append_bytes(data)
def decode(self, decoder):
decoder.align()
encoded = []
for length in decoder.read_length_determinant_chunks():
encoded.append(decoder.read_bytes(self.LENGTH_MULTIPLIER * length))
return b''.join(encoded).decode(self.ENCODING)
class MembersType(Type):
def __init__(self,
name,
root_members,
additions,
type_name):
super(MembersType, self).__init__(name, type_name)
self.root_members = root_members
self.additions = additions
self.optionals = [
member
for member in root_members
if member.optional or member.default is not None
]
def encode(self, data, encoder):
if self.additions is not None:
offset = encoder.offset()
encoder.append_bit(0)
self.encode_root(data, encoder)
if len(self.additions) > 0:
if self.encode_additions(data, encoder):
encoder.set_bit(offset)
else:
self.encode_root(data, encoder)
def encode_root(self, data, encoder):
for optional in self.optionals:
if optional.optional:
encoder.append_bit(optional.name in data)
elif optional.name in data:
encoder.append_bit(not optional.is_default(data[optional.name]))
else:
encoder.append_bit(0)
for member in self.root_members:
self.encode_member(member, data, encoder)
def encode_additions(self, data, encoder):
# Encode extension additions.
presence_bits = 0
addition_encoders = []
number_of_precence_bits = 0
try:
for addition in self.additions:
presence_bits <<= 1
addition_encoder = encoder.__class__()
number_of_precence_bits += 1
if isinstance(addition, AdditionGroup):
addition.encode_addition_group(data, addition_encoder)
else:
self.encode_member(addition,
data,
addition_encoder,
encode_default=True)
if addition_encoder.number_of_bits > 0 or addition.name in data:
addition_encoders.append(addition_encoder)
presence_bits |= 1
except EncodeError:
pass
# Return false if no extension additions are present.
if not addition_encoders:
return False
# Presence bit field.
number_of_additions = len(self.additions)
presence_bits <<= (number_of_additions - number_of_precence_bits)
encoder.append_normally_small_length(number_of_additions)
encoder.append_non_negative_binary_integer(presence_bits,
number_of_additions)
# Embed each encoded extension addition in an open type (add a
# length field and multiple of 8 bits).
encoder.align()
for addition_encoder in addition_encoders:
addition_encoder.align_always()
encoder.append_length_determinant(addition_encoder.number_of_bytes())
encoder += addition_encoder
return True
def encode_addition_group(self, data, encoder):
self.encode_root(data, encoder)
if (encoder.are_all_bits_zero()
and (encoder.number_of_bits == len(self.optionals))):
encoder.reset()
def encode_member(self, member, data, encoder, encode_default=False):
name = member.name
if name in data:
try:
if member.default is None:
member.encode(data[name], encoder)
elif not member.is_default(data[name]) or encode_default:
member.encode(data[name], encoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
elif member.optional or member.default is not None:
pass
else:
raise EncodeError(
"{} member '{}' not found in {}.".format(
self.__class__.__name__,
name,
data))
def decode(self, decoder):
if self.additions is not None:
if decoder.read_bit():
decoded = self.decode_root(decoder)
decoded.update(self.decode_additions(decoder))
else:
decoded = self.decode_root(decoder)
else:
decoded = self.decode_root(decoder)
return decoded
def decode_root(self, decoder):
values = {}
optionals = {
optional: decoder.read_bit()
for optional in self.optionals
}
for member in self.root_members:
if optionals.get(member, True):
try:
value = member.decode(decoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
values[member.name] = value
elif member.has_default():
values[member.name] = member.default
return values
def decode_additions(self, decoder):
# Presence bit field.
length = decoder.read_normally_small_length()
presence_bits = decoder.read_non_negative_binary_integer(length)
decoder.align()
decoded = {}
for i in range(length):
if presence_bits & (1 << (length - i - 1)):
# Open type decoding.
open_type_length = decoder.read_length_determinant()
offset = decoder.number_of_bits
if i < len(self.additions):
addition = self.additions[i]
try:
if isinstance(addition, AdditionGroup):
decoded.update(addition.decode(decoder))
else:
decoded[addition.name] = addition.decode(decoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(addition)
raise e
else:
decoder.skip_bits(8 * open_type_length)
alignment_bits = (offset - decoder.number_of_bits) % 8
if alignment_bits != 0:
decoder.skip_bits(8 - alignment_bits)
return decoded
def __repr__(self):
return '{}({}, [{}])'.format(
self.__class__.__name__,
self.name,
', '.join([repr(member) for member in self.root_members]))
class ArrayType(Type):
def __init__(self,
name,
element_type,
minimum,
maximum,
has_extension_marker,
type_name):
super(ArrayType, self).__init__(name, type_name)
self.element_type = element_type
self.minimum = minimum
self.maximum = maximum
self.has_extension_marker = has_extension_marker
if is_unbound(minimum, maximum):
self.number_of_bits = None
else:
size = maximum - minimum
self.number_of_bits = integer_as_number_of_bits(size)
def encode(self, data, encoder):
if self.has_extension_marker:
if self.minimum <= len(data) <= self.maximum:
encoder.append_bit(0)
else:
encoder.append_bit(1)
encoder.align()
encoder.append_length_determinant(len(data))
for entry in data:
self.element_type.encode(entry, encoder)
return
if self.number_of_bits is None:
return self.encode_unbound(data, encoder)
elif self.minimum != self.maximum:
encoder.append_constrained_whole_number(len(data),
self.minimum,
self.maximum,
self.number_of_bits)
for entry in data:
self.element_type.encode(entry, encoder)
def encode_unbound(self, data, encoder):
encoder.align()
for offset, length in encoder.append_length_determinant_chunks(len(data)):
for entry in data[offset:offset + length]:
self.element_type.encode(entry, encoder)
def decode(self, decoder):
length = None
if self.has_extension_marker:
bit = decoder.read_bit()
if bit:
decoder.align()
length = decoder.read_length_determinant()
if length is not None:
pass
elif self.number_of_bits is None:
return self.decode_unbound(decoder)
elif self.minimum != self.maximum:
length = decoder.read_constrained_whole_number(self.minimum,
self.maximum,
self.number_of_bits)
else:
length = self.minimum
decoded = []
for _ in range(length):
decoded_element = self.element_type.decode(decoder)
decoded.append(decoded_element)
return decoded
def decode_unbound(self, decoder):
decoder.align()
decoded = []
for length in decoder.read_length_determinant_chunks():
for _ in range(length):
decoded_element = self.element_type.decode(decoder)
decoded.append(decoded_element)
return decoded
def __repr__(self):
return '{}({}, {})'.format(self.__class__.__name__,
self.name,
self.element_type)
class Boolean(Type):
def __init__(self, name):
super(Boolean, self).__init__(name, 'BOOLEAN')
def encode(self, data, encoder):
encoder.append_bit(bool(data))
def decode(self, decoder):
return bool(decoder.read_bit())
class Integer(Type):
def __init__(self, name):
super(Integer, self).__init__(name, 'INTEGER')
self.minimum = None
self.maximum = None
self.has_extension_marker = False
self.number_of_bits = None
self.number_of_indefinite_bits = None
def set_restricted_to_range(self, minimum, maximum, has_extension_marker):
self.has_extension_marker = has_extension_marker
if minimum == 'MIN' or maximum == 'MAX':
return
self.minimum = minimum
self.maximum = maximum
size = self.maximum - self.minimum
self.number_of_bits = integer_as_number_of_bits(size)
if size <= 65535:
self.number_of_indefinite_bits = None
else:
number_of_bits = ((self.number_of_bits + 7) // 8 - 1).bit_length()
self.number_of_indefinite_bits = number_of_bits
def encode(self, data, encoder):
if self.has_extension_marker:
if self.minimum <= data <= self.maximum:
encoder.append_bit(0)
else:
encoder.append_bit(1)
encoder.align()
encoder.append_unconstrained_whole_number(data)
return
if self.number_of_bits is None:
encoder.align()
encoder.append_unconstrained_whole_number(data)
else:
if self.number_of_indefinite_bits is None:
number_of_bits = self.number_of_bits
else:
number_of_bytes = size_as_number_of_bytes(data - self.minimum)
number_of_bits = 8 * number_of_bytes
encoder.append_constrained_whole_number(
number_of_bytes - 1,
0,
2 ** self.number_of_indefinite_bits,
self.number_of_indefinite_bits)
encoder.align()
encoder.append_constrained_whole_number(data,
self.minimum,
self.maximum,
number_of_bits)
def decode(self, decoder):
if self.has_extension_marker:
if decoder.read_bit():
decoder.align()
return decoder.read_unconstrained_whole_number()
if self.number_of_bits is None:
decoder.align()
return decoder.read_unconstrained_whole_number()
else:
if self.number_of_indefinite_bits is None:
number_of_bits = self.number_of_bits
else:
number_of_bytes = decoder.read_constrained_whole_number(
0,
2 ** self.number_of_indefinite_bits,
self.number_of_indefinite_bits)
number_of_bytes += 1
number_of_bits = (8 * number_of_bytes)
decoder.align()
return decoder.read_constrained_whole_number(self.minimum,
self.maximum,
number_of_bits)
class Real(Type):
def __init__(self, name):
super(Real, self).__init__(name, 'REAL')
def encode(self, data, encoder):
encoded = encode_real(data)
encoder.align()
encoder.append_length_determinant(len(encoded))
encoder.append_bytes(encoded)
def decode(self, decoder):
decoder.align()
length = decoder.read_length_determinant()
return decode_real(bytearray(decoder.read_bytes(length)))
class Null(Type):
def __init__(self, name):
super(Null, self).__init__(name, 'NULL')
def encode(self, _, _encoder):
pass
def decode(self, _):
return None
class BitString(Type):
def __init__(self,
name,
named_bits,
minimum,
maximum,
has_extension_marker):
super(BitString, self).__init__(name, 'BIT STRING')
self.minimum = minimum
self.maximum = maximum
self.has_extension_marker = has_extension_marker
self.named_bits = named_bits
self.has_named_bits = named_bits is not None
if is_unbound(minimum, maximum):
self.number_of_bits = None
else:
size = self.maximum - self.minimum
self.number_of_bits = integer_as_number_of_bits(size)
def is_default(self, value):
clean_value = clean_bit_string_value(value,
self.has_named_bits)
clean_default = clean_bit_string_value(self.default,
self.has_named_bits)
return clean_value == clean_default
def rstrip_zeros(self, data, number_of_bits):
data, number_of_bits = rstrip_bit_string_zeros(bytearray(data))
if self.minimum is not None:
if number_of_bits < self.minimum:
number_of_bits = self.minimum
number_of_bytes = ((number_of_bits + 7) // 8)
data += (number_of_bytes - len(data)) * b'\x00'
return (data, number_of_bits)
def encode(self, data, encoder):
data, number_of_bits = data
if self.has_extension_marker:
if self.minimum <= number_of_bits <= self.maximum:
encoder.append_bit(0)
else:
raise NotImplementedError(
'BIT STRING extension is not yet implemented.')
if self.has_named_bits:
data, number_of_bits = self.rstrip_zeros(data, number_of_bits)
if self.number_of_bits is None:
return self.encode_unbound(data, number_of_bits, encoder)
elif self.minimum != self.maximum:
encoder.append_constrained_whole_number(number_of_bits,
self.minimum,
self.maximum,
self.number_of_bits)
encoder.align()
elif self.minimum > 16:
encoder.align()
encoder.append_bits(data, number_of_bits)
def encode_unbound(self, data, number_of_bits, encoder):
encoder.align()
for offset, length in encoder.append_length_determinant_chunks(number_of_bits):
encoder.append_bits(data[offset // 8:(offset + length + 7) // 8], length)
def decode(self, decoder):
if self.has_extension_marker:
if decoder.read_bit():
raise NotImplementedError(
'BIT STRING extension is not yet implemented.')
if self.number_of_bits is None:
return self.decode_unbound(decoder)
else:
number_of_bits = self.minimum
if self.minimum != self.maximum:
number_of_bits = decoder.read_constrained_whole_number(
self.minimum,
self.maximum,
self.number_of_bits)
decoder.align()
elif self.minimum > 16:
decoder.align()
value = decoder.read_bits(number_of_bits)
return (value, number_of_bits)
def decode_unbound(self, decoder):
decoder.align()
decoded = []
number_of_bits = 0
for length in decoder.read_length_determinant_chunks():
decoded.append(decoder.read_bits(length))
number_of_bits += length
return (b''.join(decoded), number_of_bits)
class OctetString(Type):
def __init__(self, name, minimum, maximum, has_extension_marker):
super(OctetString, self).__init__(name, 'OCTET STRING')
self.set_size_range(minimum, maximum, has_extension_marker)
def set_size_range(self, minimum, maximum, has_extension_marker):
self.minimum = minimum
self.maximum = maximum
self.has_extension_marker = has_extension_marker
if is_unbound(minimum, maximum):
self.number_of_bits = None
else:
size = self.maximum - self.minimum
if size == 0 and self.maximum >= 65536:
self.number_of_bits = None
else:
self.number_of_bits = integer_as_number_of_bits(size)
def encode(self, data, encoder):
align = True
if self.has_extension_marker:
if self.minimum <= len(data) <= self.maximum:
encoder.append_bit(0)
else:
encoder.append_bit(1)
encoder.align()
encoder.append_length_determinant(len(data))
encoder.append_bytes(data)
return
if self.number_of_bits is None:
return self.encode_unbound(data, encoder)
elif self.minimum != self.maximum:
encoder.append_constrained_whole_number(len(data),
self.minimum,
self.maximum,
self.number_of_bits)
elif self.maximum <= 2:
align = False
if align:
encoder.align()
encoder.append_bytes(data)
def encode_unbound(self, data, encoder):
encoder.align()
for offset, length in encoder.append_length_determinant_chunks(len(data)):
encoder.align()
encoder.append_bytes(data[offset:offset + length])
def decode(self, decoder):
align = True
if self.has_extension_marker:
bit = decoder.read_bit()
if bit:
decoder.align()
length = decoder.read_length_determinant()
return decoder.read_bytes(length)
if self.number_of_bits is None:
return self.decode_unbound(decoder)
else:
length = self.minimum
if self.minimum != self.maximum:
length = decoder.read_constrained_whole_number(
self.minimum,
self.maximum,
self.number_of_bits)
elif self.maximum <= 2:
align = False
if align:
decoder.align()
return decoder.read_bytes(length)
def decode_unbound(self, decoder):
decoder.align()
decoded = []
for length in decoder.read_length_determinant_chunks():
decoder.align()
decoded.append(decoder.read_bytes(length))
return b''.join(decoded)
class ObjectIdentifier(Type):
def __init__(self, name):
super(ObjectIdentifier, self).__init__(name, 'OBJECT IDENTIFIER')
def encode(self, data, encoder):
encoded_subidentifiers = encode_object_identifier(data)
encoder.align()
encoder.append_length_determinant(len(encoded_subidentifiers))
encoder.append_bytes(bytearray(encoded_subidentifiers))
def decode(self, decoder):
decoder.align()
length = decoder.read_length_determinant()
data = decoder.read_bytes(length)
return decode_object_identifier(bytearray(data), 0, len(data))
class Enumerated(Type):
def __init__(self, name, values, numeric):
super(Enumerated, self).__init__(name, 'ENUMERATED')
root, additions = enum_values_split(values)
root = sorted(root, key=itemgetter(1))
# Root.
index_to_data, data_to_index = self.create_maps(root,
numeric)
self.root_index_to_data = index_to_data
self.root_data_to_index = data_to_index
self.root_number_of_bits = integer_as_number_of_bits(len(index_to_data) - 1)
if numeric:
self.root_data_to_value = {k: k for k in enum_values_as_dict(root)}
else:
self.root_data_to_value = {v: k for k, v in enum_values_as_dict(root).items()}
# Optional additions.
if additions is None:
index_to_data = None
data_to_index = None
else:
index_to_data, data_to_index = self.create_maps(additions,
numeric)
self.additions_index_to_data = index_to_data
self.additions_data_to_index = data_to_index
def create_maps(self, items, numeric):
if numeric:
index_to_data = {
index: value[1]
for index, value in enumerate(items)
}
else:
index_to_data = {
index: value[0]
for index, value in enumerate(items)
}
data_to_index = {
data: index
for index, data in index_to_data.items()
}
return index_to_data, data_to_index
def format_root_indexes(self):
return format_or(sorted(list(self.root_index_to_data)))
def encode(self, data, encoder):
if self.additions_index_to_data is None:
index = self.root_data_to_index[data]
encoder.append_non_negative_binary_integer(index,
self.root_number_of_bits)
else:
if data in self.root_data_to_index:
encoder.append_bit(0)
index = self.root_data_to_index[data]
encoder.append_non_negative_binary_integer(index,
self.root_number_of_bits)
else:
encoder.append_bit(1)
index = self.additions_data_to_index[data]
encoder.append_normally_small_non_negative_whole_number(index)
def decode(self, decoder):
if self.additions_index_to_data is None:
return self.decode_root(decoder)
else:
additions = decoder.read_bit()
if additions == 0:
return self.decode_root(decoder)
else:
index = decoder.read_normally_small_non_negative_whole_number()
if index in self.additions_index_to_data:
return self.additions_index_to_data[index]
else:
return None
def decode_root(self, decoder):
index = decoder.read_non_negative_binary_integer(self.root_number_of_bits)
try:
data = self.root_index_to_data[index]
except KeyError:
raise DecodeError(
'Expected enumeration index {}, but got {}.'.format(
self.format_root_indexes(), index))
return data
class Sequence(MembersType):
def __init__(self,
name,
root_members,
additions):
super(Sequence, self).__init__(name,
root_members,
additions,
'SEQUENCE')
class SequenceOf(ArrayType):
def __init__(self,
name,
element_type,
minimum,
maximum,
has_extension_marker):
super(SequenceOf, self).__init__(name,
element_type,
minimum,
maximum,
has_extension_marker,
'SEQUENCE OF')
class Set(MembersType):
def __init__(self,
name,
root_members,
additions):
super(Set, self).__init__(name,
root_members,
additions,
'SET')
class SetOf(ArrayType):
def __init__(self,
name,
element_type,
minimum,
maximum,
has_extension_marker):
super(SetOf, self).__init__(name,
element_type,
minimum,
maximum,
has_extension_marker,
'SET OF')
class Choice(Type):
def __init__(self, name, root_members, additions):
super(Choice, self).__init__(name, 'CHOICE')
# Root.
index_to_member, name_to_index = self.create_maps(root_members)
self.root_index_to_member = index_to_member
self.root_name_to_index = name_to_index
self.maximum = (len(root_members) - 1)
self.root_number_of_bits = integer_as_number_of_bits(self.maximum)
if self.maximum <= 65535:
self.number_of_indefinite_bits = None
else:
number_of_bits = ((self.root_number_of_bits + 7) // 8 - 1).bit_length()
self.number_of_indefinite_bits = number_of_bits
# Optional additions.
if additions is None:
index_to_member = None
name_to_index = None
else:
index_to_member, name_to_index = self.create_maps(additions)
self.additions_index_to_member = index_to_member
self.additions_name_to_index = name_to_index
def create_maps(self, members):
index_to_member = {
index: member
for index, member in enumerate(members)
}
name_to_index = {
member.name: index
for index, member in enumerate(members)
}
return index_to_member, name_to_index
def format_root_indexes(self):
return format_or(sorted(list(self.root_index_to_member)))
def format_names(self):
members = list(self.root_index_to_member.values())
if self.additions_index_to_member is not None:
members += list(self.additions_index_to_member.values())
return format_or(sorted([member.name for member in members]))
def encode(self, data, encoder):
if self.additions_index_to_member is not None:
if data[0] in self.root_name_to_index:
encoder.append_bit(0)
self.encode_root(data, encoder)
else:
encoder.append_bit(1)
self.encode_additions(data, encoder)
else:
self.encode_root(data, encoder)
def encode_root(self, data, encoder):
try:
index = self.root_name_to_index[data[0]]
except KeyError:
raise EncodeError(
"Expected choice {}, but got '{}'.".format(
self.format_names(),
data[0]))
if len(self.root_index_to_member) > 1:
self.encode_root_index(index, encoder)
member = self.root_index_to_member[index]
try:
member.encode(data[1], encoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
def encode_root_index(self, index, encoder):
if self.number_of_indefinite_bits is None:
number_of_bits = self.root_number_of_bits
else:
number_of_bytes = size_as_number_of_bytes(index)
number_of_bits = 8 * number_of_bytes
encoder.append_constrained_whole_number(
number_of_bytes - 1,
0,
2 ** self.number_of_indefinite_bits,
self.number_of_indefinite_bits)
encoder.align()
encoder.append_constrained_whole_number(index,
0,
self.maximum,
number_of_bits)
def encode_additions(self, data, encoder):
try:
index = self.additions_name_to_index[data[0]]
except KeyError:
raise EncodeError(
"Expected choice {}, but got '{}'.".format(
self.format_names(),
data[0]))
addition_encoder = encoder.__class__()
addition = self.additions_index_to_member[index]
try:
addition.encode(data[1], addition_encoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(addition)
raise e
# Embed encoded extension addition in an open type (add a
# length field and multiple of 8 bits).
addition_encoder.align_always()
encoder.append_normally_small_non_negative_whole_number(index)
encoder.align()
encoder.append_length_determinant(addition_encoder.number_of_bytes())
encoder += addition_encoder
def decode(self, decoder):
if self.additions_index_to_member is not None:
if decoder.read_bit():
return self.decode_additions(decoder)
else:
return self.decode_root(decoder)
else:
return self.decode_root(decoder)
def decode_root(self, decoder):
if len(self.root_index_to_member) > 1:
index = self.decode_root_index(decoder)
else:
index = 0
try:
member = self.root_index_to_member[index]
except KeyError:
raise DecodeError(
'Expected choice index {}, but got {}.'.format(
self.format_root_indexes(), index))
try:
return (member.name, member.decode(decoder))
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
def decode_root_index(self, decoder):
if self.number_of_indefinite_bits is None:
number_of_bits = self.root_number_of_bits
else:
number_of_bytes = decoder.read_constrained_whole_number(
0,
2 ** self.number_of_indefinite_bits,
self.number_of_indefinite_bits)
number_of_bytes += 1
number_of_bits = (8 * number_of_bytes)
decoder.align()
return decoder.read_constrained_whole_number(0,
self.maximum,
number_of_bits)
def decode_additions(self, decoder):
index = decoder.read_normally_small_non_negative_whole_number()
if index in self.additions_index_to_member:
addition = self.additions_index_to_member[index]
else:
addition = None
# Open type decoding.
decoder.align()
length = 8 * decoder.read_length_determinant()
offset = decoder.number_of_bits
if addition is None:
name = None
decoded = None
else:
name = addition.name
try:
decoded = addition.decode(decoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(addition)
raise e
length -= (offset - decoder.number_of_bits)
decoder.skip_bits(length)
return (name, decoded)
def __repr__(self):
return 'Choice({}, [{}])'.format(
self.name,
', '.join([repr(member)
for member in self.root_name_to_index]))
class UTF8String(Type):
def __init__(self, name):
super(UTF8String, self).__init__(name, 'UTF8String')
def encode(self, data, encoder):
encoded = data.encode('utf-8')
encoder.align()
for offset, length in encoder.append_length_determinant_chunks(len(encoded)):
encoder.append_bytes(encoded[offset:offset + length])
def decode(self, decoder):
decoder.align()
encoded = []
for length in decoder.read_length_determinant_chunks():
encoded.append(decoder.read_bytes(length))
return b''.join(encoded).decode('utf-8')
class NumericString(KnownMultiplierStringType):
ALPHABET = bytearray(NUMERIC_STRING.encode('ascii'))
ENCODE_MAP = {v: i for i, v in enumerate(ALPHABET)}
DECODE_MAP = {i: v for i, v in enumerate(ALPHABET)}
PERMITTED_ALPHABET = PermittedAlphabet(ENCODE_MAP,
DECODE_MAP)
class PrintableString(KnownMultiplierStringType):
ALPHABET = bytearray(PRINTABLE_STRING.encode('ascii'))
ENCODE_MAP = {v: v for v in ALPHABET}
DECODE_MAP = {v: v for v in ALPHABET}
PERMITTED_ALPHABET = PermittedAlphabet(ENCODE_MAP,
DECODE_MAP)
class IA5String(KnownMultiplierStringType):
ALPHABET = bytearray(IA5_STRING.encode('ascii'))
ENCODE_DECODE_MAP = {v: v for v in ALPHABET}
PERMITTED_ALPHABET = PermittedAlphabet(ENCODE_DECODE_MAP,
ENCODE_DECODE_MAP)
class BMPString(KnownMultiplierStringType):
ENCODING = 'utf-16-be'
ALPHABET = BMP_STRING
ENCODE_DECODE_MAP = {ord(v): ord(v) for v in ALPHABET}
PERMITTED_ALPHABET = PermittedAlphabet(ENCODE_DECODE_MAP,
ENCODE_DECODE_MAP)
class VisibleString(KnownMultiplierStringType):
ALPHABET = bytearray(VISIBLE_STRING.encode('ascii'))
ENCODE_DECODE_MAP = {v: v for v in ALPHABET}
PERMITTED_ALPHABET = PermittedAlphabet(ENCODE_DECODE_MAP,
ENCODE_DECODE_MAP)
class GeneralString(StringType):
ENCODING = 'latin-1'
class GraphicString(StringType):
ENCODING = 'latin-1'
class TeletexString(StringType):
ENCODING = 'iso-8859-1'
class UniversalString(StringType):
ENCODING = 'utf-32-be'
LENGTH_MULTIPLIER = 4
class ObjectDescriptor(GraphicString):
pass
class UTCTime(VisibleString):
def encode(self, data, encoder):
encoded = restricted_utc_time_from_datetime(data)
return super(UTCTime, self).encode(encoded, encoder)
def decode(self, decoder):
decoded = super(UTCTime, self).decode(decoder)
return restricted_utc_time_to_datetime(decoded)
class GeneralizedTime(VisibleString):
def encode(self, data, encoder):
enceded = restricted_generalized_time_from_datetime(data)
return super(GeneralizedTime, self).encode(enceded, encoder)
def decode(self, decoder):
decoded = super(GeneralizedTime, self).decode(decoder)
return restricted_generalized_time_to_datetime(decoded)
class Date(Type):
def __init__(self, name):
super(Date, self).__init__(name, 'DATE')
immediate = Integer('immediate')
near_future = Integer('near_future')
near_past = Integer('near_past')
reminder = Integer('reminder')
immediate.set_restricted_to_range(2005, 2020, False)
near_future.set_restricted_to_range(2021, 2276, False)
near_past.set_restricted_to_range(1749, 2004, False)
reminder.set_restricted_to_range('MIN', 1748, False)
year = Choice('year',
[immediate, near_future, near_past, reminder],
None)
month = Integer('month')
day = Integer('day')
month.set_restricted_to_range(1, 12, False)
day.set_restricted_to_range(1, 31, False)
self._inner = Sequence('DATE-ENCODING',
[year, month, day],
None)
def encode(self, data, encoder):
if 2005 <= data.year <= 2020:
choice = 'immediate'
elif 2021 <= data.year <= 2276:
choice = 'near_future'
elif 1749 <= data.year <= 2004:
choice = 'near_past'
else:
choice = 'reminder'
data = {
'year': (choice, data.year),
'month': data.month,
'day': data.day
}
return self._inner.encode(data, encoder)
def decode(self, decoder):
decoded = self._inner.decode(decoder)
return datetime.date(decoded['year'][1],
decoded['month'],
decoded['day'])
class TimeOfDay(Type):
def __init__(self, name):
super(TimeOfDay, self).__init__(name, 'TIME-OF-DAY')
hours = Integer('hours')
minutes = Integer('minutes')
seconds = Integer('seconds')
hours.set_restricted_to_range(0, 24, False)
minutes.set_restricted_to_range(0, 59, False)
seconds.set_restricted_to_range(0, 60, False)
self._inner = Sequence('TIME-OF-DAY-ENCODING',
[hours, minutes, seconds],
None)
def encode(self, data, encoder):
data = {
'hours': data.hour,
'minutes': data.minute,
'seconds': data.second
}
return self._inner.encode(data, encoder)
def decode(self, decoder):
decoded = self._inner.decode(decoder)
return datetime.time(decoded['hours'],
decoded['minutes'],
decoded['seconds'])
class DateTime(Type):
def __init__(self, name):
super(DateTime, self).__init__(name, 'DATE-TIME')
self._inner = Sequence('DATE-TIME-ENCODING',
[Date('date'), TimeOfDay('time')],
None)
def encode(self, data, encoder):
data = {
'date': data,
'time': data
}
return self._inner.encode(data, encoder)
def decode(self, decoder):
decoded = self._inner.decode(decoder)
return datetime.datetime(decoded['date'].year,
decoded['date'].month,
decoded['date'].day,
decoded['time'].hour,
decoded['time'].minute,
decoded['time'].second)
class OpenType(Type):
def __init__(self, name):
super(OpenType, self).__init__(name, 'OpenType')
def encode(self, data, encoder):
encoder.align()
encoder.append_length_determinant(len(data))
encoder.append_bytes(data)
def decode(self, decoder):
decoder.align()
length = decoder.read_length_determinant()
return decoder.read_bytes(length)
class Any(Type):
def __init__(self, name):
super(Any, self).__init__(name, 'ANY')
def encode(self, _, _encoder):
raise NotImplementedError('ANY is not yet implemented.')
def decode(self, _decoder):
raise NotImplementedError('ANY is not yet implemented.')
class Recursive(compiler.Recursive, Type):
def __init__(self, name, type_name, module_name):
super(Recursive, self).__init__(name, 'RECURSIVE')
self.type_name = type_name
self.module_name = module_name
self._inner = None
def set_inner_type(self, inner):
self._inner = inner
def encode(self, data, encoder):
self._inner.encode(data, encoder)
def decode(self, decoder):
return self._inner.decode(decoder)
class AdditionGroup(Sequence):
pass
class CompiledType(compiler.CompiledType):
def encode(self, data):
encoder = Encoder()
try:
self._type.encode(data, encoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
return encoder.as_bytearray()
def decode(self, data):
decoder = Decoder(bytearray(data))
try:
return self._type.decode(decoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
class Compiler(compiler.Compiler):
def process_type(self, type_name, type_descriptor, module_name):
compiled_type = self.compile_type(type_name,
type_descriptor,
module_name)
return CompiledType(compiled_type)
def compile_type(self, name, type_descriptor, module_name):
module_name = self.get_module_name(type_descriptor, module_name)
type_name = type_descriptor['type']
if type_name == 'SEQUENCE':
compiled = Sequence(
name,
*self.compile_members(type_descriptor['members'],
module_name))
elif type_name == 'SEQUENCE OF':
compiled = SequenceOf(name,
self.compile_type('',
type_descriptor['element'],
module_name),
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'SET':
compiled = Set(
name,
*self.compile_members(type_descriptor['members'],
module_name,
sort_by_tag=True))
elif type_name == 'SET OF':
compiled = SetOf(name,
self.compile_type('',
type_descriptor['element'],
module_name),
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'CHOICE':
compiled = Choice(name,
*self.compile_members(
type_descriptor['members'],
module_name,
flat_additions=True))
elif type_name == 'INTEGER':
compiled = Integer(name)
elif type_name == 'REAL':
compiled = Real(name)
elif type_name == 'ENUMERATED':
compiled = Enumerated(name,
self.get_enum_values(type_descriptor,
module_name),
self._numeric_enums)
elif type_name == 'BOOLEAN':
compiled = Boolean(name)
elif type_name == 'OBJECT IDENTIFIER':
compiled = ObjectIdentifier(name)
elif type_name == 'OCTET STRING':
compiled = OctetString(name,
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'TeletexString':
compiled = TeletexString(name)
elif type_name == 'NumericString':
permitted_alphabet = self.get_permitted_alphabet(type_descriptor)
compiled = NumericString(name,
*self.get_size_range(type_descriptor,
module_name),
permitted_alphabet=permitted_alphabet)
elif type_name == 'PrintableString':
permitted_alphabet = self.get_permitted_alphabet(type_descriptor)
compiled = PrintableString(name,
*self.get_size_range(type_descriptor,
module_name),
permitted_alphabet=permitted_alphabet)
elif type_name == 'IA5String':
permitted_alphabet = self.get_permitted_alphabet(type_descriptor)
compiled = IA5String(name,
*self.get_size_range(type_descriptor,
module_name),
permitted_alphabet=permitted_alphabet)
elif type_name == 'BMPString':
permitted_alphabet = self.get_permitted_alphabet(type_descriptor)
compiled = BMPString(name,
*self.get_size_range(type_descriptor,
module_name),
permitted_alphabet=permitted_alphabet)
elif type_name == 'VisibleString':
permitted_alphabet = self.get_permitted_alphabet(type_descriptor)
compiled = VisibleString(name,
*self.get_size_range(type_descriptor,
module_name),
permitted_alphabet=permitted_alphabet)
elif type_name == 'GeneralString':
compiled = GeneralString(name)
elif type_name == 'UTF8String':
compiled = UTF8String(name)
elif type_name == 'GraphicString':
compiled = GraphicString(name)
elif type_name == 'UTCTime':
compiled = UTCTime(name)
elif type_name == 'UniversalString':
compiled = UniversalString(name)
elif type_name == 'GeneralizedTime':
compiled = GeneralizedTime(name)
elif type_name == 'DATE':
compiled = Date(name)
elif type_name == 'TIME-OF-DAY':
compiled = TimeOfDay(name)
elif type_name == 'DATE-TIME':
compiled = DateTime(name)
elif type_name == 'BIT STRING':
compiled = BitString(name,
self.get_named_bits(type_descriptor,
module_name),
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'ANY':
compiled = Any(name)
elif type_name == 'ANY DEFINED BY':
compiled = Any(name)
elif type_name == 'NULL':
compiled = Null(name)
elif type_name == 'OpenType':
compiled = OpenType(name)
elif type_name == 'EXTERNAL':
compiled = Sequence(
name,
*self.compile_members(self.external_type_descriptor()['members'],
module_name))
elif type_name == 'ObjectDescriptor':
compiled = ObjectDescriptor(name)
else:
if type_name in self.types_backtrace:
compiled = Recursive(name,
type_name,
module_name)
self.recursive_types.append(compiled)
else:
compiled = self.compile_user_type(name,
type_name,
module_name)
if 'tag' in type_descriptor:
compiled = self.set_compiled_tag(compiled, type_descriptor)
if 'restricted-to' in type_descriptor:
compiled = self.set_compiled_restricted_to(compiled,
type_descriptor,
module_name)
return compiled
def set_compiled_tag(self, compiled, type_descriptor):
compiled = self.copy(compiled)
tag = type_descriptor['tag']
class_prio = CLASS_PRIO[tag.get('class', 'CONTEXT_SPECIFIC')]
class_number = tag['number']
compiled.tag = (class_prio, class_number)
return compiled
def compile_members(self,
members,
module_name,
sort_by_tag=False,
flat_additions=False):
compiled_members = []
in_extension = False
additions = None
for member in members:
if member == EXTENSION_MARKER:
in_extension = not in_extension
if in_extension:
additions = []
elif in_extension:
self.compile_extension_member(member,
module_name,
additions,
flat_additions)
else:
self.compile_root_member(member,
module_name,
compiled_members)
if sort_by_tag:
compiled_members = sorted(compiled_members, key=attrgetter('tag'))
return compiled_members, additions
def compile_extension_member(self,
member,
module_name,
additions,
flat_additions):
if isinstance(member, list):
if flat_additions:
for memb in member:
compiled_member = self.compile_member(memb,
module_name)
additions.append(compiled_member)
else:
compiled_member, _ = self.compile_members(member,
module_name)
compiled_group = AdditionGroup('ExtensionAddition',
compiled_member,
None)
additions.append(compiled_group)
else:
compiled_member = self.compile_member(member,
module_name)
additions.append(compiled_member)
def get_permitted_alphabet(self, type_descriptor):
def char_range(begin, end):
return ''.join([chr(char)
for char in range(ord(begin), ord(end) + 1)])
if 'from' not in type_descriptor:
return
permitted_alphabet = type_descriptor['from']
value = ''
for item in permitted_alphabet:
if isinstance(item, tuple):
value += char_range(item[0], item[1])
else:
value += item
value = sorted(value)
encode_map = {ord(v): i for i, v in enumerate(value)}
decode_map = {i: ord(v) for i, v in enumerate(value)}
return PermittedAlphabet(encode_map, decode_map)
def compile_dict(specification, numeric_enums=False):
return Compiler(specification, numeric_enums).process()
def decode_full_length(_data):
raise DecodeError('Decode length is not supported for this codec.')
asn1tools-0.169.0/asn1tools/codecs/permitted_alphabet.py 0000664 0000000 0000000 00000001155 15245442746 0023223 0 ustar 00root root 0000000 0000000 """Permitted alphabet.
"""
import string
try:
unichr
except NameError:
unichr = chr
NUMERIC_STRING = ' 0123456789'
PRINTABLE_STRING = (string.ascii_uppercase
+ string.ascii_lowercase
+ string.digits
+ " '()+,-./:=?")
IA5_STRING = ''.join([chr(v) for v in range(128)])
# ud800 - udfff are reserved code points for utf-16 surrogates.
# at this point, do not support code points in supplementary planes.
BMP_STRING = ''.join([unichr(v) for v in range(65536) if v < 0xd800 or v > 0xdfff])
VISIBLE_STRING = ''.join([chr(v) for v in range(32, 127)])
asn1tools-0.169.0/asn1tools/codecs/type_checker.py 0000664 0000000 0000000 00000026263 15245442746 0022042 0 ustar 00root root 0000000 0000000 """Python type checker.
"""
import sys
import datetime
from copy import copy
from . import EncodeError, ErrorWithLocation
from . import compiler
from . import format_or
STRING_TYPES = [
'OBJECT IDENTIFIER',
'TeletexString',
'NumericString',
'PrintableString',
'IA5String',
'VisibleString',
'GeneralString',
'UTF8String',
'BMPString',
'GraphicString',
'UniversalString',
'ObjectDescriptor'
]
class Type(object):
TYPE = None
def __init__(self, name):
self.name = name
def set_size_range(self, minimum, maximum, has_extension_marker):
pass
def set_default(self, value):
pass
def encode(self, data):
if not isinstance(data, self.TYPE):
raise EncodeError(
'Expected data of type {}, but got {}.'.format(self.TYPE.__name__,
data))
class Boolean(Type):
TYPE = bool
class Integer(Type):
def encode(self, data):
if sys.version_info[0] > 2:
if not isinstance(data, (int, str)):
raise EncodeError(
'Expected data of type int or str, but got {}.'.format(
data))
else:
if not isinstance(data, (int, long, str, unicode)):
raise EncodeError(
'Expected data of type int or str, but got {}.'.format(
data))
class Float(Type):
def encode(self, data):
if sys.version_info[0] > 2:
if not isinstance(data, (float, int)):
raise EncodeError(
'Expected data of type float or int, but got {}.'.format(
data))
else:
if not isinstance(data, (float, int, long)):
raise EncodeError(
'Expected data of type float or int, but got {}.'.format(
data))
class Null(Type):
def encode(self, data):
if data is not None:
raise EncodeError('Expected None, but got {}.'.format(data))
class BitString(Type):
def encode(self, data):
if (not isinstance(data, tuple)
or len(data) != 2
or not isinstance(data[0], (bytes, bytearray))
or not isinstance(data[1], int)):
raise EncodeError(
'Expected data of type tuple(bytes, int), but got {}.'.format(
data))
if 8 * len(data[0]) < data[1]:
raise EncodeError(
'Expected at least {} bit(s) data, but got {}.'.format(
data[1],
8 * len(data[0])))
class Bytes(Type):
def encode(self, data):
if not isinstance(data, (bytes, bytearray)):
raise EncodeError(
'Expected data of type bytes or bytearray, but got {}.'.format(
data))
class String(Type):
def encode(self, data):
if sys.version_info[0] > 2:
if not isinstance(data, str):
raise EncodeError(
'Expected data of type str, but got {}.'.format(data))
else:
if not isinstance(data, (str, unicode)):
raise EncodeError(
'Expected data of type str, but got {}.'.format(data))
class Dict(Type):
TYPE = dict
def __init__(self, name, members):
super(Dict, self).__init__(name)
self.members = members
def encode(self, data):
super(Dict, self).encode(data)
self.encode_members(data)
def encode_members(self, data):
for member in self.members:
name = member.name
if name in data:
try:
member.encode(data[name])
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
class List(Type):
TYPE = list
def __init__(self, name, element_type):
super(List, self).__init__(name)
self.element_type = element_type
def encode(self, data):
super(List, self).encode(data)
self.encode_members(data)
def encode_members(self, data):
for entry in data:
self.element_type.encode(entry)
class Enumerated(Type):
def __init__(self, name, numeric_enums):
super(Enumerated, self).__init__(name)
self._numeric_enums = numeric_enums
def encode(self, data):
if self._numeric_enums:
self.encode_integer(data)
else:
self.encode_string(data)
def encode_integer(self, data):
if sys.version_info[0] > 2:
if not isinstance(data, int):
raise EncodeError(
'Expected data of type int, but got {}.'.format(
data))
else:
if not isinstance(data, (int, long)):
raise EncodeError(
'Expected data of type int, but got {}.'.format(
data))
def encode_string(self, data):
if sys.version_info[0] > 2:
if not isinstance(data, str):
raise EncodeError(
'Expected data of type str, but got {}.'.format(data))
else:
if not isinstance(data, (str, unicode)):
raise EncodeError(
'Expected data of type str, but got {}.'.format(data))
class Choice(Type):
def __init__(self, name, members):
super(Choice, self).__init__(name)
self.members = members
self.name_to_member = {member.name: member for member in self.members}
def format_names(self):
return format_or(sorted([member.name for member in self.members]))
def encode(self, data):
if sys.version_info[0] > 2:
if (not isinstance(data, tuple)
or len(data) != 2
or not isinstance(data[0], str)):
raise EncodeError(
'Expected data of type tuple(str, object), but got {}.'.format(
data))
else:
if (not isinstance(data, tuple)
or len(data) != 2
or not isinstance(data[0], (str, unicode))):
raise EncodeError(
'Expected data of type tuple(str, object), but got {}.'.format(
data))
try:
member = self.name_to_member[data[0]]
except KeyError:
raise EncodeError(
"Expected choice {}, but got '{}'.".format(
self.format_names(),
data[0]))
try:
member.encode(data[1])
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
class Date(Type):
def encode(self, data):
if not isinstance(data, datetime.date):
raise EncodeError(
'Expected data of type datetime.date, but got {}.'.format(
data))
class TimeOfDay(Type):
def encode(self, data):
if not isinstance(data, datetime.time):
raise EncodeError(
'Expected data of type datetime.time, but got {}.'.format(
data))
class DateTime(Type):
def encode(self, data):
if not isinstance(data, datetime.datetime):
raise EncodeError(
'Expected data of type datetime.datetime, but got {}.'.format(
data))
class Skip(Type):
def encode(self, data):
pass
class Recursive(compiler.Recursive, Type):
def __init__(self, name, type_name, module_name):
super(Recursive, self).__init__(name)
self.type_name = type_name
self.module_name = module_name
self.inner = None
def set_inner_type(self, inner):
self.inner = copy(inner)
def encode(self, data):
try:
self.inner.encode(data)
except ErrorWithLocation as e:
# Add member location
e.add_location(self.inner)
raise e
class CompiledType(compiler.CompiledType):
def encode(self, data):
try:
self._type.encode(data)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
class Compiler(compiler.Compiler):
def process_type(self, type_name, type_descriptor, module_name):
compiled_type = self.compile_type(type_name,
type_descriptor,
module_name)
return CompiledType(compiled_type)
def compile_type(self, name, type_descriptor, module_name):
module_name = type_descriptor.get('module-name', module_name)
type_name = type_descriptor['type']
if type_name in ['SEQUENCE', 'SET']:
members, _ = self.compile_members(type_descriptor['members'],
module_name)
compiled = Dict(name, members)
elif type_name in ['SEQUENCE OF', 'SET OF']:
element_type = self.compile_type('',
type_descriptor['element'],
module_name)
compiled = List(name, element_type)
elif type_name == 'CHOICE':
members, _ = self.compile_members(type_descriptor['members'],
module_name)
compiled = Choice(name, members)
elif type_name == 'INTEGER':
compiled = Integer(name)
elif type_name == 'REAL':
compiled = Float(name)
elif type_name == 'BOOLEAN':
compiled = Boolean(name)
elif type_name == 'OCTET STRING':
compiled = Bytes(name)
elif type_name in ['UTCTime', 'GeneralizedTime', 'DATE-TIME']:
compiled = DateTime(name)
elif type_name == 'TIME-OF-DAY':
compiled = TimeOfDay(name)
elif type_name == 'DATE':
compiled = Date(name)
elif type_name == 'BIT STRING':
compiled = BitString(name)
elif type_name in STRING_TYPES:
compiled = String(name)
elif type_name == 'ENUMERATED':
compiled = Enumerated(name, self._numeric_enums)
elif type_name in ['ANY', 'ANY DEFINED BY', 'OpenType']:
compiled = Skip(name)
elif type_name == 'NULL':
compiled = Null(name)
elif type_name == 'EXTERNAL':
members, _ = self.compile_members(
self.external_type_descriptor()['members'],
module_name)
compiled = Dict(name, members)
else:
if type_name in self.types_backtrace:
compiled = Recursive(name,
type_name,
module_name)
self.recursive_types.append(compiled)
else:
compiled = self.compile_user_type(name,
type_name,
module_name)
return compiled
def compile_dict(specification, numeric_enums=False):
return Compiler(specification, numeric_enums).process()
asn1tools-0.169.0/asn1tools/codecs/uper.py 0000664 0000000 0000000 00000055431 15245442746 0020347 0 ustar 00root root 0000000 0000000 """Unaligned Packed Encoding Rules (UPER) codec.
"""
from . import DecodeError, ErrorWithLocation
from . import per
from . import restricted_utc_time_to_datetime
from . import restricted_utc_time_from_datetime
from . import restricted_generalized_time_to_datetime
from . import restricted_generalized_time_from_datetime
from .per import to_int
from .per import to_byte_array
from .per import integer_as_number_of_bits
from .per import PermittedAlphabet
from .per import Type
from .per import Boolean
from .per import Real
from .per import Null
from .per import Enumerated
from .per import ObjectIdentifier
from .per import Sequence
from .per import Set
from .per import UTF8String
from .per import GeneralString
from .per import GraphicString
from .per import TeletexString
from .per import UniversalString
from .per import ObjectDescriptor
from .per import Any
from .per import Recursive
from .permitted_alphabet import NUMERIC_STRING
from .permitted_alphabet import PRINTABLE_STRING
from .permitted_alphabet import IA5_STRING
from .permitted_alphabet import BMP_STRING
from .permitted_alphabet import VISIBLE_STRING
class Encoder(per.Encoder):
def align(self):
pass
class Decoder(per.Decoder):
def align(self):
pass
class KnownMultiplierStringType(per.KnownMultiplierStringType):
ENCODING = 'ascii'
PERMITTED_ALPHABET = ''
def __init__(self,
name,
minimum=None,
maximum=None,
has_extension_marker=None,
permitted_alphabet=None):
super(KnownMultiplierStringType, self).__init__(name,
self.__class__.__name__)
self.set_size_range(minimum, maximum, has_extension_marker)
if permitted_alphabet is None:
permitted_alphabet = self.PERMITTED_ALPHABET
self.permitted_alphabet = permitted_alphabet
self.bits_per_character = integer_as_number_of_bits(
len(permitted_alphabet) - 1)
def encode(self, data, encoder):
if self.has_extension_marker:
encoder.append_bit(0)
if self.number_of_bits is None:
return self.encode_unbound(data, encoder)
elif self.minimum != self.maximum:
encoder.append_non_negative_binary_integer(len(data) - self.minimum,
self.number_of_bits)
for value in data:
encoder.append_non_negative_binary_integer(
self.permitted_alphabet.encode(
to_int(value.encode(self.ENCODING))),
self.bits_per_character)
def decode(self, decoder):
if self.has_extension_marker:
bit = decoder.read_bit()
if bit:
raise NotImplementedError(
'String size extension is not yet implemented.')
if self.number_of_bits is None:
return self.decode_unbound(decoder)
else:
length = self.minimum
if self.minimum != self.maximum:
length += decoder.read_non_negative_binary_integer(self.number_of_bits)
data = bytearray()
for _ in range(length):
value = decoder.read_non_negative_binary_integer(self.bits_per_character)
value = self.permitted_alphabet.decode(value)
data += to_byte_array(value, self.bits_per_character)
return data.decode(self.ENCODING)
class ArrayType(per.ArrayType):
def encode(self, data, encoder):
if self.has_extension_marker:
if self.minimum <= len(data) <= self.maximum:
encoder.append_bit(0)
else:
encoder.append_bit(1)
encoder.append_length_determinant(len(data))
for entry in data:
self.element_type.encode(entry, encoder)
return
if self.number_of_bits is None:
return self.encode_unbound(data, encoder)
elif self.minimum != self.maximum:
encoder.append_non_negative_binary_integer(len(data) - self.minimum,
self.number_of_bits)
for entry in data:
self.element_type.encode(entry, encoder)
def decode(self, decoder):
length = None
if self.has_extension_marker:
bit = decoder.read_bit()
if bit:
length = decoder.read_length_determinant()
if length is not None:
pass
elif self.number_of_bits is None:
return self.decode_unbound(decoder)
else:
length = self.minimum
if self.minimum != self.maximum:
length += decoder.read_non_negative_binary_integer(
self.number_of_bits)
decoded = []
for _ in range(length):
decoded_element = self.element_type.decode(decoder)
decoded.append(decoded_element)
return decoded
class Integer(Type):
def __init__(self, name):
super(Integer, self).__init__(name, 'INTEGER')
self.minimum = None
self.maximum = None
self.has_extension_marker = None
self.number_of_bits = None
def set_restricted_to_range(self, minimum, maximum, has_extension_marker):
self.has_extension_marker = has_extension_marker
if minimum == 'MIN' or maximum == 'MAX':
return
self.minimum = minimum
self.maximum = maximum
size = self.maximum - self.minimum
self.number_of_bits = integer_as_number_of_bits(size)
def encode(self, data, encoder):
if self.has_extension_marker:
if self.minimum <= data <= self.maximum:
encoder.append_bit(0)
else:
encoder.append_bit(1)
encoder.append_unconstrained_whole_number(data)
return
if self.number_of_bits is None:
encoder.append_unconstrained_whole_number(data)
else:
encoder.append_non_negative_binary_integer(data - self.minimum,
self.number_of_bits)
def decode(self, decoder):
if self.has_extension_marker:
if decoder.read_bit():
return decoder.read_unconstrained_whole_number()
if self.number_of_bits is None:
return decoder.read_unconstrained_whole_number()
else:
value = decoder.read_non_negative_binary_integer(self.number_of_bits)
return value + self.minimum
def __repr__(self):
return 'Integer({})'.format(self.name)
class BitString(per.BitString):
def encode(self, data, encoder):
data, number_of_bits = data
if self.has_extension_marker:
if self.minimum <= number_of_bits <= self.maximum:
encoder.append_bit(0)
else:
raise NotImplementedError(
'BIT STRING extension is not yet implemented.')
if self.has_named_bits:
data, number_of_bits = self.rstrip_zeros(data, number_of_bits)
if self.number_of_bits is None:
return self.encode_unbound(data, number_of_bits, encoder)
elif self.minimum != self.maximum:
encoder.append_non_negative_binary_integer(
number_of_bits - self.minimum,
self.number_of_bits)
encoder.append_bits(data, number_of_bits)
def decode(self, decoder):
if self.has_extension_marker:
if decoder.read_bit():
raise NotImplementedError(
'BIT STRING extension is not yet implemented.')
if self.number_of_bits is None:
return self.decode_unbound(decoder)
else:
number_of_bits = self.minimum
if self.minimum != self.maximum:
number_of_bits += decoder.read_non_negative_binary_integer(
self.number_of_bits)
value = decoder.read_bits(number_of_bits)
return (value, number_of_bits)
class OctetString(per.OctetString):
def encode(self, data, encoder):
if self.has_extension_marker:
if self.minimum <= len(data) <= self.maximum:
encoder.append_bit(0)
else:
encoder.append_bit(1)
encoder.align()
encoder.append_length_determinant(len(data))
encoder.append_bytes(data)
return
if self.number_of_bits is None:
return self.encode_unbound(data, encoder)
elif self.minimum != self.maximum:
encoder.append_non_negative_binary_integer(len(data) - self.minimum,
self.number_of_bits)
encoder.append_bytes(data)
def decode(self, decoder):
if self.has_extension_marker:
bit = decoder.read_bit()
if bit:
length = decoder.read_length_determinant()
return decoder.read_bytes(length)
if self.number_of_bits is None:
return self.decode_unbound(decoder)
else:
length = self.minimum
if self.minimum != self.maximum:
length += decoder.read_non_negative_binary_integer(
self.number_of_bits)
return decoder.read_bytes(length)
class SequenceOf(ArrayType):
def __init__(self,
name,
element_type,
minimum,
maximum,
has_extension_marker):
super(SequenceOf, self).__init__(name,
element_type,
minimum,
maximum,
has_extension_marker,
'SEQUENCE OF')
class SetOf(ArrayType):
def __init__(self,
name,
element_type,
minimum,
maximum,
has_extension_marker):
super(SetOf, self).__init__(name,
element_type,
minimum,
maximum,
has_extension_marker,
'SET OF')
class Choice(per.Choice):
def encode_root_index(self, index, encoder):
encoder.append_non_negative_binary_integer(index, self.root_number_of_bits)
def decode_root_index(self, decoder):
return decoder.read_non_negative_binary_integer(self.root_number_of_bits)
class NumericString(KnownMultiplierStringType):
ALPHABET = bytearray(NUMERIC_STRING.encode('ascii'))
ENCODE_MAP = {v: i for i, v in enumerate(ALPHABET)}
DECODE_MAP = {i: v for i, v in enumerate(ALPHABET)}
PERMITTED_ALPHABET = PermittedAlphabet(ENCODE_MAP,
DECODE_MAP)
class PrintableString(KnownMultiplierStringType):
ALPHABET = bytearray(PRINTABLE_STRING.encode('ascii'))
ENCODE_MAP = {v: v for v in ALPHABET}
DECODE_MAP = {v: v for v in ALPHABET}
PERMITTED_ALPHABET = PermittedAlphabet(ENCODE_MAP,
DECODE_MAP)
class IA5String(KnownMultiplierStringType):
ALPHABET = bytearray(IA5_STRING.encode('ascii'))
ENCODE_DECODE_MAP = {v: v for v in ALPHABET}
PERMITTED_ALPHABET = PermittedAlphabet(ENCODE_DECODE_MAP,
ENCODE_DECODE_MAP)
class BMPString(KnownMultiplierStringType):
ENCODING = 'utf-16-be'
ALPHABET = BMP_STRING
ENCODE_DECODE_MAP = {ord(v): ord(v) for v in ALPHABET}
PERMITTED_ALPHABET = PermittedAlphabet(ENCODE_DECODE_MAP,
ENCODE_DECODE_MAP)
class VisibleString(KnownMultiplierStringType):
ALPHABET = bytearray(VISIBLE_STRING.encode('ascii'))
ENCODE_DECODE_MAP = {v: v for v in ALPHABET}
PERMITTED_ALPHABET = PermittedAlphabet(ENCODE_DECODE_MAP,
ENCODE_DECODE_MAP)
class UTCTime(VisibleString):
def encode(self, data, encoder):
encoded = restricted_utc_time_from_datetime(data)
return super(UTCTime, self).encode(encoded, encoder)
def decode(self, decoder):
decoded = super(UTCTime, self).decode(decoder)
return restricted_utc_time_to_datetime(decoded)
class GeneralizedTime(VisibleString):
def encode(self, data, encoder):
enceded = restricted_generalized_time_from_datetime(data)
return super(GeneralizedTime, self).encode(enceded, encoder)
def decode(self, decoder):
decoded = super(GeneralizedTime, self).decode(decoder)
return restricted_generalized_time_to_datetime(decoded)
class Date(per.Date):
def __init__(self, name):
super(Date, self).__init__(name)
immediate = Integer('immediate')
near_future = Integer('near_future')
near_past = Integer('near_past')
reminder = Integer('reminder')
immediate.set_restricted_to_range(2005, 2020, False)
near_future.set_restricted_to_range(2021, 2276, False)
near_past.set_restricted_to_range(1749, 2004, False)
reminder.set_restricted_to_range('MIN', 1748, False)
year = Choice('year',
[immediate, near_future, near_past, reminder],
None)
month = Integer('month')
day = Integer('day')
month.set_restricted_to_range(1, 12, False)
day.set_restricted_to_range(1, 31, False)
self._inner = Sequence('DATE-ENCODING',
[year, month, day],
None)
class TimeOfDay(per.TimeOfDay):
def __init__(self, name):
super(TimeOfDay, self).__init__(name)
hours = Integer('hours')
minutes = Integer('minutes')
seconds = Integer('seconds')
hours.set_restricted_to_range(0, 24, False)
minutes.set_restricted_to_range(0, 59, False)
seconds.set_restricted_to_range(0, 60, False)
self._inner = Sequence('TIME-OF-DAY-ENCODING',
[hours, minutes, seconds],
None)
class DateTime(per.DateTime):
def __init__(self, name):
super(DateTime, self).__init__(name)
self._inner = Sequence('DATE-TIME-ENCODING',
[Date('date'), TimeOfDay('time')],
None)
class OpenType(Type):
def __init__(self, name):
super(OpenType, self).__init__(name, 'OpenType')
def encode(self, data, encoder):
encoder.align()
encoder.append_length_determinant(len(data))
encoder.append_bytes(data)
def decode(self, decoder):
decoder.align()
length = decoder.read_length_determinant()
return decoder.read_bytes(length)
class CompiledType(per.CompiledType):
def encode(self, data):
encoder = Encoder()
try:
self._type.encode(data, encoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
return encoder.as_bytearray()
def decode(self, data):
decoder = Decoder(bytearray(data))
try:
return self._type.decode(decoder)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
class Compiler(per.Compiler):
def process_type(self, type_name, type_descriptor, module_name):
compiled_type = self.compile_type(type_name,
type_descriptor,
module_name)
return CompiledType(compiled_type)
def compile_type(self, name, type_descriptor, module_name):
module_name = self.get_module_name(type_descriptor, module_name)
type_name = type_descriptor['type']
if type_name == 'SEQUENCE':
compiled = Sequence(
name,
*self.compile_members(type_descriptor['members'],
module_name))
elif type_name == 'SEQUENCE OF':
compiled = SequenceOf(name,
self.compile_type('',
type_descriptor['element'],
module_name),
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'SET':
compiled = Set(
name,
*self.compile_members(type_descriptor['members'],
module_name,
sort_by_tag=True))
elif type_name == 'SET OF':
compiled = SetOf(name,
self.compile_type('',
type_descriptor['element'],
module_name),
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'CHOICE':
compiled = Choice(name,
*self.compile_members(
type_descriptor['members'],
module_name,
flat_additions=True))
elif type_name == 'INTEGER':
compiled = Integer(name)
elif type_name == 'REAL':
compiled = Real(name)
elif type_name == 'ENUMERATED':
compiled = Enumerated(name,
self.get_enum_values(type_descriptor,
module_name),
self._numeric_enums)
elif type_name == 'BOOLEAN':
compiled = Boolean(name)
elif type_name == 'OBJECT IDENTIFIER':
compiled = ObjectIdentifier(name)
elif type_name == 'OCTET STRING':
compiled = OctetString(name,
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'TeletexString':
compiled = TeletexString(name)
elif type_name == 'NumericString':
permitted_alphabet = self.get_permitted_alphabet(type_descriptor)
compiled = NumericString(name,
*self.get_size_range(type_descriptor,
module_name),
permitted_alphabet=permitted_alphabet)
elif type_name == 'PrintableString':
permitted_alphabet = self.get_permitted_alphabet(type_descriptor)
compiled = PrintableString(name,
*self.get_size_range(type_descriptor,
module_name),
permitted_alphabet=permitted_alphabet)
elif type_name == 'IA5String':
permitted_alphabet = self.get_permitted_alphabet(type_descriptor)
compiled = IA5String(name,
*self.get_size_range(type_descriptor,
module_name),
permitted_alphabet=permitted_alphabet)
elif type_name == 'BMPString':
permitted_alphabet = self.get_permitted_alphabet(type_descriptor)
compiled = BMPString(name,
*self.get_size_range(type_descriptor,
module_name),
permitted_alphabet=permitted_alphabet)
elif type_name == 'VisibleString':
permitted_alphabet = self.get_permitted_alphabet(type_descriptor)
compiled = VisibleString(name,
*self.get_size_range(type_descriptor,
module_name),
permitted_alphabet=permitted_alphabet)
elif type_name == 'GeneralString':
compiled = GeneralString(name)
elif type_name == 'UTF8String':
compiled = UTF8String(name)
elif type_name == 'GraphicString':
compiled = GraphicString(name)
elif type_name == 'UTCTime':
compiled = UTCTime(name)
elif type_name == 'UniversalString':
compiled = UniversalString(name)
elif type_name == 'GeneralizedTime':
compiled = GeneralizedTime(name)
elif type_name == 'DATE':
compiled = Date(name)
elif type_name == 'TIME-OF-DAY':
compiled = TimeOfDay(name)
elif type_name == 'DATE-TIME':
compiled = DateTime(name)
elif type_name == 'BIT STRING':
compiled = BitString(name,
self.get_named_bits(type_descriptor,
module_name),
*self.get_size_range(type_descriptor,
module_name))
elif type_name == 'ANY':
compiled = Any(name)
elif type_name == 'ANY DEFINED BY':
compiled = Any(name)
elif type_name == 'NULL':
compiled = Null(name)
elif type_name == 'OpenType':
compiled = OpenType(name)
elif type_name == 'EXTERNAL':
compiled = Sequence(
name,
*self.compile_members(self.external_type_descriptor()['members'],
module_name))
elif type_name == 'ObjectDescriptor':
compiled = ObjectDescriptor(name)
else:
if type_name in self.types_backtrace:
compiled = Recursive(name,
type_name,
module_name)
self.recursive_types.append(compiled)
else:
compiled = self.compile_user_type(name,
type_name,
module_name)
if 'tag' in type_descriptor:
compiled = self.set_compiled_tag(compiled, type_descriptor)
if 'restricted-to' in type_descriptor:
compiled = self.set_compiled_restricted_to(compiled,
type_descriptor,
module_name)
return compiled
def compile_dict(specification, numeric_enums=False):
return Compiler(specification, numeric_enums).process()
def decode_full_length(_data):
raise DecodeError('Decode length is not supported for this codec.')
asn1tools-0.169.0/asn1tools/codecs/xer.py 0000664 0000000 0000000 00000053550 15245442746 0020172 0 ustar 00root root 0000000 0000000 """XML Encoding Rules (XER) codec.
"""
import time
import sys
from xml.etree import ElementTree
import binascii
import datetime
from ..parser import EXTENSION_MARKER
from . import BaseType, format_bytes, ErrorWithLocation
from . import EncodeError
from . import DecodeError
from . import compiler
from . import format_or
from . import utc_time_to_datetime
from . import utc_time_from_datetime
from . import generalized_time_to_datetime
from . import generalized_time_from_datetime
from .compiler import enum_values_as_dict
def indent_xml(element, indent, level=0):
i = "\n" + level * indent
if len(element):
if not element.text or not element.text.strip():
element.text = i + indent
if not element.tail or not element.tail.strip():
element.tail = i
for element in element:
indent_xml(element, indent, level + 1)
if not element.tail or not element.tail.strip():
element.tail = i
else:
if level and (not element.tail or not element.tail.strip()):
element.tail = i
class Type(BaseType):
def __init__(self, name, type_name):
super().__init__(name.replace(' ', '_'), type_name)
def set_size_range(self, minimum, maximum, has_extension_marker):
pass
def encode_of(self, data):
# Used by ArrayType
return self.encode(data)
def decode_of(self, element):
# Used by ArrayType
return self.decode(element)
class StringType(Type):
def __init__(self, name, type_name=None):
if type_name is None:
type_name = self.__class__.__name__
super(StringType, self).__init__(name, type_name)
def encode(self, data):
element = ElementTree.Element(self.name)
if len(data) > 0:
element.text = data
return element
def decode(self, element):
if element.text is None:
return u''
else:
if sys.version_info[0] > 2:
return element.text
else:
return unicode(element.text)
def __repr__(self):
return '{}({})'.format(self.__class__.__name__,
self.name)
class MembersType(Type):
def __init__(self, name, members, type_name):
super(MembersType, self).__init__(name, type_name)
self.members = members
def encode(self, data):
element = ElementTree.Element(self.name)
for member in self.members:
name = member.name
if name in data:
try:
member_element = member.encode(data[name])
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
elif member.optional or member.has_default():
continue
else:
raise EncodeError(
"{} member '{}' not found in {}.".format(
self.__class__.__name__,
name,
data))
element.append(member_element)
return element
def decode(self, element):
values = {}
for member in self.members:
name = member.name
member_element = element.find(name)
if member_element is not None:
try:
value = member.decode(member_element)
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
values[name] = value
elif member.optional:
pass
elif member.has_default():
values[name] = member.get_default()
return values
def __repr__(self):
return '{}({}, [{}])'.format(
self.__class__.__name__,
self.name,
', '.join([repr(member) for member in self.members]))
class ArrayType(Type):
def __init__(self, name, element_type, type_name):
super(ArrayType, self).__init__(name, type_name)
self.element_type = element_type
def encode(self, data):
element = ElementTree.Element(self.name)
for entry in data:
element.append(self.element_type.encode_of(entry))
return element
def decode(self, element):
values = []
for member_element in list(element):
value = self.element_type.decode_of(member_element)
values.append(value)
return values
def __repr__(self):
return '{}({}, {})'.format(self.__class__.__name__,
self.name,
self.element_type)
class Boolean(Type):
def __init__(self, name):
super(Boolean, self).__init__(name, 'BOOLEAN')
def encode(self, data):
element = ElementTree.Element(self.name)
ElementTree.SubElement(element, 'true' if data else 'false')
return element
def decode(self, element):
return element.find('true') is not None
def encode_of(self, data):
return ElementTree.Element('true' if data else 'false')
def decode_of(self, element):
return element.tag == 'true'
class Integer(Type):
def __init__(self, name):
super(Integer, self).__init__(name, 'INTEGER')
def encode(self, data):
element = ElementTree.Element(self.name)
element.text = str(data)
return element
def decode(self, element):
return int(element.text)
class Real(Type):
def __init__(self, name):
super(Real, self).__init__(name, 'REAL')
def encode(self, data):
data = float(data)
exponent = 0
while abs(data) >= 10:
data /= 10
exponent += 1
element = ElementTree.Element(self.name)
element.text = '{}E{}'.format(data, exponent)
return element
def decode(self, element):
return float(element.text)
class Null(Type):
def __init__(self, name):
super(Null, self).__init__(name, 'NULL')
def encode(self, data):
return ElementTree.Element(self.name)
def decode(self, element):
return None
class BitString(Type):
def __init__(self, name):
super(BitString, self).__init__(name, 'BIT STRING')
def encode(self, data):
element = ElementTree.Element(self.name)
if data[1] > 0:
encoded = int(binascii.hexlify(data[0]), 16)
encoded |= (0x80 << (8 * len(data[0])))
element.text = bin(encoded)[10:10 + data[1]].upper()
return element
def decode(self, element):
encoded = element.text
if encoded is None:
number_of_bits = 0
decoded = b''
else:
number_of_bits = len(encoded)
decoded = int(encoded, 2)
decoded |= (0x80 << number_of_bits)
rest = (number_of_bits % 8)
if rest != 0:
decoded <<= (8 - rest)
decoded = binascii.unhexlify(hex(decoded).rstrip('L')[4:])
return (decoded, number_of_bits)
class OctetString(Type):
def __init__(self, name):
super(OctetString, self).__init__(name, 'OCTET STRING')
def encode(self, data):
element = ElementTree.Element(self.name)
if len(data) > 0:
element.text = format_bytes(data).upper()
return element
def decode(self, element):
if element.text is None:
return b''
else:
if len(element.text) % 2:
return binascii.unhexlify(element.text.zfill(len(element.text)+1))
return binascii.unhexlify(element.text)
class ObjectIdentifier(StringType):
def __init__(self, name):
super(ObjectIdentifier, self).__init__(name, 'OBJECT IDENTIFIER')
def decode(self, element):
if element.text is None:
raise DecodeError("Expected an OBJECT IDENTIFIER, but got ''.")
return element.text
class Enumerated(Type):
def __init__(self, name, values, numeric):
super(Enumerated, self).__init__(name, 'ENUMERATED')
if numeric:
self.data_to_value = enum_values_as_dict(values)
self.value_to_data = {v: k for k, v in self.data_to_value.items()}
else:
self.value_to_data = {
k: k for k in enum_values_as_dict(values).values()
}
self.data_to_value = self.value_to_data
self.has_extension_marker = (EXTENSION_MARKER in values)
def format_names(self):
return format_or(sorted(list(self.value_to_data.values())))
def format_values(self):
return format_or(sorted(list(self.value_to_data)))
def encode(self, data):
try:
value = self.data_to_value[data]
except KeyError:
raise EncodeError(
"Expected enumeration value {}, but got '{}'.".format(
self.format_names(),
data))
element = ElementTree.Element(self.name)
element.append(ElementTree.Element(value))
return element
def decode(self, element):
value = element[0].tag
if value in self.value_to_data:
return self.value_to_data[value]
elif self.has_extension_marker:
return None
else:
raise DecodeError(
"Expected enumeration value {}, but got '{}'.".format(
self.format_values(), value))
def encode_of(self, data):
try:
value = self.data_to_value[data]
except KeyError:
raise EncodeError(
"Expected enumeration value {}, but got '{}'.".format(
self.format_names(),
data))
return ElementTree.Element(value)
def decode_of(self, element):
value = element.tag
try:
return self.value_to_data[value]
except KeyError:
raise DecodeError(
"Expected enumeration value {}, but got '{}'.".format(
self.format_values(), value))
class Sequence(MembersType):
def __init__(self, name, members):
super(Sequence, self).__init__(name, members, 'SEQUENCE')
class SequenceOf(ArrayType):
def __init__(self, name, element_type):
super(SequenceOf, self).__init__(name,
element_type,
'SEQUENCE OF')
class Set(MembersType):
def __init__(self, name, members):
super(Set, self).__init__(name, members, 'SET')
class SetOf(ArrayType):
def __init__(self, name, element_type):
super(SetOf, self).__init__(name,
element_type,
'SET OF')
class Choice(Type):
def __init__(self, name, members, has_extension_marker):
super(Choice, self).__init__(name, 'CHOICE')
self.members = members
self.name_to_member = {member.name: member for member in self.members}
self.has_extension_marker = has_extension_marker
def format_names(self):
return format_or(sorted([member.name for member in self.members]))
def encode(self, data):
try:
member = self.name_to_member[data[0]]
except KeyError:
raise EncodeError(
"Expected choice {}, but got '{}'.".format(
self.format_names(),
data[0]))
element = ElementTree.Element(self.name)
try:
element.append(member.encode(data[1]))
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
return element
def decode(self, element):
member_element = element[0]
name = member_element.tag
if name in self.name_to_member:
member = self.name_to_member[name]
elif self.has_extension_marker:
return (None, None)
else:
raise DecodeError(
"Expected choice {}, but got '{}'.".format(
self.format_names(), name))
try:
return (name, member.decode(member_element))
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
def encode_of(self, data):
try:
member = self.name_to_member[data[0]]
except KeyError:
e = EncodeError(
"Expected choice {}, but got '{}'.".format(
self.format_names(),
data[0]))
# e.add_location(self.name)
raise e
try:
return member.encode(data[1])
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
def decode_of(self, element):
name = element.tag
try:
member = self.name_to_member[name]
except KeyError:
raise DecodeError(
"Expected choice {}, but got '{}'.".format(
self.format_names(), name))
try:
return (name, member.decode(element))
except ErrorWithLocation as e:
# Add member location
e.add_location(member)
raise e
def __repr__(self):
return 'Choice({}, [{}])'.format(
self.name,
', '.join([repr(member) for member in self.members]))
class UTF8String(StringType):
pass
class NumericString(StringType):
pass
class PrintableString(StringType):
pass
class IA5String(StringType):
pass
class VisibleString(StringType):
pass
class GeneralString(StringType):
pass
class BMPString(StringType):
pass
class GraphicString(StringType):
pass
class UniversalString(StringType):
pass
class TeletexString(StringType):
pass
class ObjectDescriptor(GraphicString):
pass
class UTCTime(Type):
def __init__(self, name):
super(UTCTime, self).__init__(name, 'UTCTime')
def encode(self, data):
element = ElementTree.Element(self.name)
element.text = utc_time_from_datetime(data)
return element
def decode(self, element):
return utc_time_to_datetime(element.text)
class GeneralizedTime(Type):
def __init__(self, name):
super(GeneralizedTime, self).__init__(name, 'GeneralizedTime')
def encode(self, data):
element = ElementTree.Element(self.name)
element.text = generalized_time_from_datetime(data)
return element
def decode(self, element):
return generalized_time_to_datetime(element.text)
class Date(StringType):
def encode(self, data):
element = ElementTree.Element(self.name)
element.text = str(data)
return element
def decode(self, element):
return datetime.date(*time.strptime(element.text, '%Y-%m-%d')[:3])
class TimeOfDay(StringType):
def encode(self, data):
element = ElementTree.Element(self.name)
element.text = str(data)
return element
def decode(self, element):
return datetime.time(*time.strptime(element.text, '%H:%M:%S')[3:6])
class DateTime(StringType):
def encode(self, data):
element = ElementTree.Element(self.name)
element.text = str(data).replace(' ', 'T')
return element
def decode(self, element):
return datetime.datetime(*time.strptime(element.text,
'%Y-%m-%dT%H:%M:%S')[:6])
class Any(Type):
def __init__(self, name):
super(Any, self).__init__(name, 'ANY')
def encode(self, data):
raise NotImplementedError('ANY is not yet implemented.')
def decode(self, element):
raise NotImplementedError('ANY is not yet implemented.')
class Recursive(compiler.Recursive, Type):
def __init__(self, name, type_name, module_name):
super(Recursive, self).__init__(name, 'RECURSIVE')
self.type_name = type_name
self.module_name = module_name
self._inner = None
def set_inner_type(self, inner):
self._inner = inner
def encode(self, data):
encoded = self._inner.encode(data)
encoded.tag = self.name
return encoded
def decode(self, element):
return self._inner.decode(element)
class CompiledType(compiler.CompiledType):
def encode(self, data, indent=None):
try:
element = self._type.encode(data)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
if indent is not None:
indent_xml(element, indent * " ")
return ElementTree.tostring(element)
def decode(self, data):
element = ElementTree.fromstring(data.decode('utf-8'))
try:
return self._type.decode(element)
except ErrorWithLocation as e:
# Add member location
e.add_location(self._type)
raise e
class Compiler(compiler.Compiler):
def process_type(self, type_name, type_descriptor, module_name):
compiled_type = self.compile_type(type_name,
type_descriptor,
module_name)
return CompiledType(compiled_type)
def compile_type(self, name, type_descriptor, module_name):
module_name = self.get_module_name(type_descriptor, module_name)
type_name = type_descriptor['type']
if type_name == 'SEQUENCE':
members, _ = self.compile_members(
type_descriptor['members'],
module_name)
compiled = Sequence(name, members)
elif type_name == 'SEQUENCE OF':
element = type_descriptor['element']
compiled = SequenceOf(name,
self.compile_type(type_descriptor.get('element_name') or element['type'],
element,
module_name))
elif type_name == 'SET':
members, _ = self.compile_members(
type_descriptor['members'],
module_name)
compiled = Set(name, members)
elif type_name == 'SET OF':
element = type_descriptor['element']
compiled = SetOf(name,
self.compile_type(type_descriptor.get('element_name') or element['type'],
element,
module_name))
elif type_name == 'CHOICE':
compiled = Choice(name,
*self.compile_members(
type_descriptor['members'],
module_name))
elif type_name == 'INTEGER':
compiled = Integer(name)
elif type_name == 'REAL':
compiled = Real(name)
elif type_name == 'ENUMERATED':
compiled = Enumerated(name,
self.get_enum_values(type_descriptor,
module_name),
self._numeric_enums)
elif type_name == 'BOOLEAN':
compiled = Boolean(name)
elif type_name == 'OBJECT IDENTIFIER':
compiled = ObjectIdentifier(name)
elif type_name == 'OCTET STRING':
compiled = OctetString(name)
elif type_name == 'TeletexString':
compiled = TeletexString(name)
elif type_name == 'NumericString':
compiled = NumericString(name)
elif type_name == 'PrintableString':
compiled = PrintableString(name)
elif type_name == 'IA5String':
compiled = IA5String(name)
elif type_name == 'VisibleString':
compiled = VisibleString(name)
elif type_name == 'GeneralString':
compiled = GeneralString(name)
elif type_name == 'UTF8String':
compiled = UTF8String(name)
elif type_name == 'BMPString':
compiled = BMPString(name)
elif type_name == 'GraphicString':
compiled = GraphicString(name)
elif type_name == 'UTCTime':
compiled = UTCTime(name)
elif type_name == 'UniversalString':
compiled = UniversalString(name)
elif type_name == 'GeneralizedTime':
compiled = GeneralizedTime(name)
elif type_name == 'DATE':
compiled = Date(name)
elif type_name == 'TIME-OF-DAY':
compiled = TimeOfDay(name)
elif type_name == 'DATE-TIME':
compiled = DateTime(name)
elif type_name == 'BIT STRING':
compiled = BitString(name)
elif type_name == 'ANY':
compiled = Any(name)
elif type_name == 'ANY DEFINED BY':
compiled = Any(name)
elif type_name == 'NULL':
compiled = Null(name)
elif type_name == 'EXTERNAL':
members, _ = self.compile_members(self.external_type_descriptor()['members'],
module_name)
compiled = Sequence(name, members)
elif type_name == 'ObjectDescriptor':
compiled = ObjectDescriptor(name)
else:
if type_name in self.types_backtrace:
compiled = Recursive(name,
type_name,
module_name)
self.recursive_types.append(compiled)
else:
compiled = self.compile_user_type(name,
type_name,
module_name)
return compiled
def compile_dict(specification, numeric_enums):
return Compiler(specification, numeric_enums).process()
def decode_full_length(_data):
raise DecodeError('Decode length is not supported for this codec.')
asn1tools-0.169.0/asn1tools/compat.py 0000664 0000000 0000000 00000002511 15245442746 0017406 0 ustar 00root root 0000000 0000000 """Python 2 & 3 compatibility.
"""
import sys
from datetime import datetime
from datetime import timedelta
from datetime import tzinfo
if sys.version_info[0] > 2:
from datetime import timezone
UTC = timezone.utc
def strptime(data, fmt):
return datetime.strptime(data, fmt)
else:
class timezone(tzinfo):
def __init__(self, offset):
self._utcoffset = offset
def utcoffset(self, dt):
return self._utcoffset
def tzname(self, dt):
return "-"
def dst(self, dt):
return timedelta(0)
UTC = timezone(timedelta(hours=0, minutes=0))
def strptime(data, fmt):
if fmt.endswith('%z'):
date = datetime.strptime(data[:-5], fmt[:-2])
try:
sign = {'-': -1, '+': 1}[data[-5]]
hours = sign * int(data[-4:-2])
minutes = sign * int(data[-2:])
except KeyError:
raise ValueError(
"time data '{}' does not match format '{}'.".format(
data,
fmt))
date = date.replace(tzinfo=timezone(timedelta(hours=hours,
minutes=minutes)))
else:
date = datetime.strptime(data, fmt)
return date
asn1tools-0.169.0/asn1tools/compiler.py 0000664 0000000 0000000 00000031737 15245442746 0017751 0 ustar 00root root 0000000 0000000 """Compile ASN.1 specifications to Python objects that can be used to
encode and decode types.
"""
try:
import diskcache
has_diskcache = True
except ImportError:
has_diskcache = False
from .parser import parse_files
from .parser import parse_string
from .codecs import compiler
from .codecs import ber
from .codecs import der
from .codecs import gser
from .codecs import jer
from .codecs import oer
from .codecs import per
from .codecs import uper
from .codecs import xer
from .codecs import type_checker
from .codecs import constraints_checker
from .errors import CompileError
from .errors import EncodeError
from .errors import DecodeError
class Specification(object):
"""This class is used to encode and decode ASN.1 types found in an
ASN.1 specification.
Instances of this class are created by the factory functions
:func:`~asn1tools.compile_files()`,
:func:`~asn1tools.compile_string()` and
:func:`~asn1tools.compile_dict()`.
"""
def __init__(self,
modules,
decode_length,
type_checkers,
constraints_checkers):
self._modules = modules
self._decode_length = decode_length
self._types = {}
duplicated = set()
for module_name in modules:
types = modules[module_name]
for type_name, type_ in types.items():
type_.type_checker = type_checkers[module_name][type_name]
type_.constraints_checker = constraints_checkers[module_name][type_name]
if type_name in duplicated:
continue
if type_name in self._types:
del self._types[type_name]
duplicated.add(type_name)
continue
self._types[type_name] = type_
@property
def types(self):
"""A dictionary of all unique types in the specification. Types found
in two or more modules are not part of this dictionary.
>>> question = foo.types['Question']
>>> question
Sequence(Question, [Integer(id), IA5String(question)])
>>> question.encode({'id': 1, 'question': 'Is 1+1=3?'})
b'0\\x0e\\x02\\x01\\x01\\x16\\x09Is 1+1=3?'
"""
return self._types
@property
def modules(self):
"""A dictionary of all modules in the specification. Unlike
:attr:`.types`, this attribute contains every type, even if
the type name was found in two or more modules.
>>> question = foo.modules['Foo']['Question']
>>> question
Sequence(Question, [Integer(id), IA5String(question)])
>>> question.encode({'id': 1, 'question': 'Is 1+1=3?'})
b'0\\x0e\\x02\\x01\\x01\\x16\\x09Is 1+1=3?'
"""
return self._modules
def encode(self,
name,
data,
check_types=True,
check_constraints=False,
**kwargs):
"""Encode given dictionary `data` as given type `name` and return the
encoded data as a bytes object.
If `check_types` is ``True`` all objects in `data` are checked
against the expected Python type for its ASN.1 type. Set
`check_types` to ``False`` to minimize the runtime overhead,
but instead get less informative error messages.
See `Types`_ for a mapping table from ASN.1 types to Python
types.
If `check_constraints` is ``True`` all objects in `data` are
checked against their ASN.1 type constraints. A
ConstraintsError exception is raised if the constraints are
not fulfilled. Set `check_constraints` to ``False`` to skip
the constraints check and minimize the runtime overhead, but
instead get less informative error messages and allow encoding
of values not fulfilling the constraints.
>>> foo.encode('Question', {'id': 1, 'question': 'Is 1+1=3?'})
b'0\\x0e\\x02\\x01\\x01\\x16\\x09Is 1+1=3?'
"""
try:
type_ = self._types[name]
except KeyError:
raise EncodeError(
"Type '{}' not found in types dictionary.".format(name))
if check_types:
type_.check_types(data)
if check_constraints:
type_.check_constraints(data)
return bytes(type_.encode(data, **kwargs))
def decode(self, name, data, check_constraints=False):
"""Decode given bytes object `data` as given type `name` and return
the decoded data as a dictionary.
If `check_constraints` is ``True`` all objects in `data` are
checked against their ASN.1 type constraints. A
ConstraintsError exception is raised if the constraints are
not fulfilled. Set `check_constraints` to ``False`` to skip
the constraints check and minimize the runtime overhead, but
instead allow decoding of values not fulfilling the
constraints.
>>> foo.decode('Question', b'0\\x0e\\x02\\x01\\x01\\x16\\x09Is 1+1=3?')
{'id': 1, 'question': 'Is 1+1=3?'}
"""
try:
type_ = self._types[name]
except KeyError:
raise DecodeError(
"Type '{}' not found in types dictionary.".format(name))
decoded = type_.decode(data)
if check_constraints:
type_.check_constraints(decoded)
return decoded
def decode_with_length(self, name, data, check_constraints=False):
"""Same as :func:`~asn1tools.compiler.Specification.decode`, but also
returns the byte length of the decoded data.
Use to get the length of indefinite-length BER encoded data.
>>> foo.decode_with_length('Question',
b'0\\x0e\\x02\\x01\\x01\\x16\\x09Is 1+1=3?')
({'id': 1, 'question': 'Is 1+1=3?'}, 16)
"""
try:
type_ = self._types[name]
except KeyError:
raise DecodeError(
"Type '{}' not found in types dictionary.".format(name))
decoded, length = type_.decode_with_length(data)
if check_constraints:
type_.check_constraints(decoded)
return decoded, length
def decode_length(self, data):
"""Decode the length of given data `data`. Returns None if not enough
data was given to decode the length.
This method only works for BER and DER codecs with definite
length in the first data encoding. Other codecs and
combinations lacks length information in the data.
>>> foo.decode_length(b'\\x30\\x0e\\x02\\x01\\x01')
16
"""
return self._decode_length(data)
def _compile_any_defined_by_type(type_, choices):
type_['choices'] = {}
for key, value in choices.items():
specification = 'A DEFINITIONS ::= BEGIN B ::= {} END'.format(value)
type_['choices'][key] = parse_string(specification)['A']['types']['B']
def _compile_any_defined_by_choices(specification,
any_defined_by_choices):
for location, choices in any_defined_by_choices.items():
module_name = location[0]
type_names = location[1:-1]
member_name = location[-1]
types = specification[module_name]['types']
if len(type_names) == 0:
_compile_any_defined_by_type(types[member_name], choices)
else:
for type_name in type_names:
types = types[type_name]
for member in types['members']:
if member['name'] != member_name:
continue
_compile_any_defined_by_type(member, choices)
break
def _compile_files_cache(filenames,
codec,
any_defined_by_choices,
encoding,
cache_dir,
numeric_enums):
key = [codec.encode('ascii')]
if isinstance(filenames, str):
filenames = [filenames]
for filename in filenames:
with open(filename, 'rb') as fin:
key.append(fin.read())
key = b''.join(key)
cache = diskcache.Cache(cache_dir)
try:
return cache[key]
except KeyError:
compiled = compile_dict(parse_files(filenames, encoding),
codec,
any_defined_by_choices,
numeric_enums)
cache[key] = compiled
return compiled
def compile_dict(specification,
codec='ber',
any_defined_by_choices=None,
numeric_enums=False):
"""Compile given ASN.1 specification dictionary and return a
:class:`~asn1tools.compiler.Specification` object that can be used
to encode and decode data structures with given codec
`codec`. `codec` may be one of ``'ber'``, ``'der'``, ``'gser'``,
``'jer'``, ``oer``, ``'per'``, ``'uper'`` and ``'xer'``.
Give `numeric_enums` as ``True`` for numeric enumeration values
instead of strings.
>>> foo = asn1tools.compile_dict(asn1tools.parse_files('foo.asn'))
"""
codecs = {
'ber': ber,
'der': der,
'gser': gser,
'jer': jer,
'oer': oer,
'per': per,
'uper': uper,
'xer': xer
}
try:
codec = codecs[codec]
except KeyError:
raise CompileError("Unsupported codec '{}'.".format(codec))
if any_defined_by_choices:
_compile_any_defined_by_choices(specification,
any_defined_by_choices)
return Specification(codec.compile_dict(specification,
numeric_enums),
codec.decode_full_length,
type_checker.compile_dict(specification,
numeric_enums),
constraints_checker.compile_dict(specification,
numeric_enums))
def compile_string(string,
codec='ber',
any_defined_by_choices=None,
numeric_enums=False):
"""Compile given ASN.1 specification string and return a
:class:`~asn1tools.compiler.Specification` object that can be used
to encode and decode data structures with given codec
`codec`. `codec` may be one of ``'ber'``, ``'der'``, ``'gser'``,
``'jer'``, ``oer``, ``'per'``, ``'uper'`` and ``'xer'``.
Give `numeric_enums` as ``True`` for numeric enumeration values
instead of strings.
>>> with open('foo.asn') as fin:
... foo = asn1tools.compile_string(fin.read())
"""
return compile_dict(parse_string(string),
codec,
any_defined_by_choices,
numeric_enums)
def compile_files(filenames,
codec='ber',
any_defined_by_choices=None,
encoding='utf-8',
cache_dir=None,
numeric_enums=False):
"""Compile given ASN.1 specification file(s) and return a
:class:`~asn1tools.compiler.Specification` object that can be used
to encode and decode data structures with given codec
`codec`. `codec` may be one of ``'ber'``, ``'der'``, ``'gser'``,
``'jer'``, ``oer``, ``'per'``, ``'uper'`` and ``'xer'``.
`encoding` is the text encoding. This argument is passed to the
built-in function `open()`.
`cache_dir` specifies the compiled files cache location in the
file system. Give as ``None`` to disable the cache. By default the
cache is disabled. The cache key is the concatenated contents of
given files and the codec name. Using a cache will significantly
reduce the compile time when recompiling the same files. The cache
directory is automatically created if it does not exist. Remove
the cache directory `cache_dir` to clear the cache.
Give `numeric_enums` as ``True`` for numeric enumeration values
instead of strings.
>>> foo = asn1tools.compile_files('foo.asn')
Give `cache_dir` as a string to use a cache.
>>> foo = asn1tools.compile_files('foo.asn', cache_dir='my_cache')
"""
if cache_dir is None:
return compile_dict(parse_files(filenames, encoding),
codec,
any_defined_by_choices,
numeric_enums)
else:
if not has_diskcache:
raise RuntimeError(
'Cache access requested, but diskcache module is missing')
return _compile_files_cache(filenames,
codec,
any_defined_by_choices,
encoding,
cache_dir,
numeric_enums)
def pre_process_dict(specification):
"""Pre-process given specification dictionary, expanding COMPONENTS OF
and adding extension markers if EXTENSIBILITY IMPLIED is active.
"""
return compiler.pre_process(specification)
asn1tools-0.169.0/asn1tools/errors.py 0000664 0000000 0000000 00000000645 15245442746 0017445 0 ustar 00root root 0000000 0000000 """Various exceptions/errors.
"""
class Error(Exception):
"""Base exception of all asn1tools exceptions.
"""
class CompileError(Error):
"""General ASN.1 compile error.
"""
class EncodeError(Error):
"""General ASN.1 encode error.
"""
class DecodeError(Error):
"""General ASN.1 decode error.
"""
class ConstraintsError(Error):
"""General ASN.1 constraints error.
"""
asn1tools-0.169.0/asn1tools/parser.py 0000664 0000000 0000000 00000203726 15245442746 0017432 0 ustar 00root root 0000000 0000000 """Convert ASN.1 specifications to Python data structures.
"""
import logging
import re
import sys
from pyparsing import Literal
from pyparsing import Keyword
from pyparsing import Word
from pyparsing import ZeroOrMore
from pyparsing import Regex
from pyparsing import printables
from pyparsing import DelimitedList
from pyparsing import Group
from pyparsing import Optional
from pyparsing import Forward
from pyparsing import StringEnd
from pyparsing import OneOrMore
from pyparsing import nums
from pyparsing import Suppress
from pyparsing import ParseException
from pyparsing import ParseSyntaxException
from pyparsing import NotAny
from pyparsing import NoMatch
from pyparsing import QuotedString
from pyparsing import Combine
from pyparsing import ParseResults
from pyparsing import lineno
from .errors import Error
LOGGER = logging.getLogger(__name__)
EXTENSION_MARKER = None
class ParseError(Error):
pass
class InternalParserError(Error):
pass
class Tokens(object):
def __init__(self, tag, tokens):
self.tag = tag
self.tokens = tokens
def __getitem__(self, index):
return self.tokens[index]
def __len__(self):
return len(self.tokens)
def __iter__(self):
for token in self.tokens:
yield token
def __bool__(self):
return len(self.tokens) > 0
def __eq__(self, other):
return other == self.tag
def __repr__(self):
return "Tokens(tag='{}', tokens='{}')".format(self.tag,
self.tokens)
class Tag(Group):
def __init__(self, tag, expr):
super(Tag, self).__init__(expr)
self.tag = tag
def postParse(self, instring, loc, tokenlist):
return Tokens(self.tag, tokenlist.asList())
def merge_dicts(dicts):
return {k: v for d in dicts for k, v in d.items()}
def convert_integer(_s, _l, tokens):
try:
return int(tokens[0])
except (IndexError, ValueError):
return tokens
def convert_real_number(_s, _l, tokens):
if '.' not in tokens[0]:
tokens = int(tokens[0])
return tokens
def convert_number(token):
if isinstance(token, list):
token = token[0]
try:
return int(token)
except (ValueError, TypeError):
return token
def convert_size(tokens):
if len(tokens) == 0:
return None
tokens = tokens[0]
if tokens[0] == 'SIZE':
values = []
for item_tokens in tokens[1].asList():
if '..' in item_tokens:
value = (convert_number(item_tokens[0]),
convert_number(item_tokens[2]))
else:
value = convert_number(item_tokens[0])
values.append(value)
return values
elif isinstance(tokens[0], dict):
if 'size' in tokens[0]:
return tokens[0]['size']
def convert_table(tokens):
tokens = tokens[0]
try:
if isinstance(tokens[1][0][0], list):
defined_object_set = tokens[1][0][0][0]
else:
defined_object_set = tokens[1][0][0]
except IndexError:
return None
try:
component_ids = tokens[4]
except IndexError:
return defined_object_set
return [defined_object_set, component_ids]
def convert_enum_values(string, location, tokens):
number = 0
values = []
used_numbers = []
root, extension = tokens
root = root.asList()
extension = extension.asList()
def add_used_numbers(items):
for item in items:
if not isinstance(item, list):
continue
item_number = item[2]
if item_number in used_numbers:
raise ParseError(
'Duplicated ENUMERATED number {} at line {}.'.format(
item_number,
lineno(location, string)))
used_numbers.append(item_number)
# Root enumeration.
add_used_numbers(root)
for token in root:
if isinstance(token, list):
values.append((token[0], token[2]))
else:
while number in used_numbers:
number += 1
used_numbers.append(number)
values.append((token, number))
number += 1
# Optional additional enumeration.
if extension:
values.append(EXTENSION_MARKER)
additional = extension[1:]
add_used_numbers(additional)
for token in additional:
if isinstance(token, list):
number = token[2]
values.append((token[0], number))
else:
if number in used_numbers:
raise ParseError(
'Duplicated ENUMERATED number {} at line {}.'.format(
number,
lineno(location, string)))
values.append((token, number))
used_numbers.append(number)
number += 1
return values
def convert_tag(tokens):
if len(tokens) > 0:
if len(tokens[0]) == 1:
tag = {
'number': int(tokens[0][0])
}
else:
tag = {
'number': convert_number(tokens[0][1]),
'class': tokens[0][0]
}
if tokens[1]:
tag['kind'] = tokens[1][0] if tokens[1] else None
return tag
def convert_value_range(_s, _l, tokens):
tokens = tokens.asList()
minimum = tokens[0]
if isinstance(minimum, list):
minimum = minimum[0]
maximum = tokens[1]
if isinstance(maximum, list):
maximum = maximum[0]
return (minimum, maximum)
def convert_inner_type_constraints(_s, _l, tokens):
tokens = tokens.asList()
components = []
if tokens[0] == 'WITH COMPONENTS':
for item_tokens in tokens[2]:
if item_tokens == '...':
value = EXTENSION_MARKER
elif len(item_tokens) == 2:
if isinstance(item_tokens[1], list):
value = item_tokens[1][0]
if isinstance(value, list):
value = value[0]
value = (item_tokens[0], value)
else:
value = (item_tokens[0], item_tokens[1])
else:
value = item_tokens
components.append(value)
return {'with-components': components}
else:
return {}
def convert_size_constraint(_s, _l, tokens):
tokens = tokens.asList()[1]
values = []
for item_tokens in tokens:
if item_tokens == '...':
value = EXTENSION_MARKER
elif '..' in item_tokens:
value = (convert_number(item_tokens[0]),
convert_number(item_tokens[2]))
else:
value = convert_number(item_tokens[0])
values.append(value)
return {'size': values}
def convert_permitted_alphabet(_s, _l, tokens):
tokens = tokens.asList()
values = []
for token in tokens[1:]:
if isinstance(token[0], list):
for char in token[0][0]:
values.append((char, char))
else:
values.append(token[0])
return {'from': values}
def convert_constraint(_s, _l, tokens):
tokens = tokens.asList()
# print('constraint:', tokens)
def convert_members(tokens):
members = []
for member_tokens in tokens:
if member_tokens in [['...'], '...']:
members.append(EXTENSION_MARKER)
continue
if member_tokens[0] == 'COMPONENTS OF':
members.append({
'components-of': member_tokens[1][0]['type']
})
continue
if member_tokens[0] == '[[':
members.append(convert_members(member_tokens[1]))
continue
if len(member_tokens) == 2:
member_tokens, qualifiers = member_tokens
qualifiers = qualifiers.asList()
else:
qualifiers = []
member = convert_type(member_tokens[2], [])
member['name'] = member_tokens[0]
if 'OPTIONAL' in qualifiers:
member['optional'] = True
if 'DEFAULT' in qualifiers:
if len(qualifiers[1]) == 0:
value = []
else:
value = convert_value(qualifiers[1], member['type'])
member['default'] = value
tag = convert_tag(member_tokens[1])
if tag:
member['tag'] = tag
members.append(member)
return members
def convert_sequence_type(_s, _l, tokens):
return {
'type': 'SEQUENCE',
'members': convert_members(tokens[2])
}
def convert_sequence_of_type(_s, _l, tokens):
is_named_element = len(tokens) == 6
converted_type = {
'type': 'SEQUENCE OF',
'element': convert_type(tokens[5 if is_named_element else 4], []),
}
if (is_named_element):
converted_type['element_name'] = tokens[3]
if len(tokens[1]) > 0:
converted_type['size'] = tokens[1][0][0]['size']
if len(tokens[1]) > 1 and tokens[1][1] == '...':
converted_type['size'].append(None)
tag = convert_tag(tokens[4 if is_named_element else 3])
if tag:
converted_type['element']['tag'] = tag
return converted_type
def convert_set_type(_s, _l, tokens):
return {
'type': 'SET',
'members': convert_members(tokens[2])
}
def convert_set_of_type(_s, _l, tokens):
is_named_element = len(tokens) == 6
converted_type = {
'type': 'SET OF',
'element': convert_type(tokens[5 if is_named_element else 4], [])
}
if (is_named_element):
converted_type['element_name'] = tokens[3]
if len(tokens[1]) > 0:
converted_type['size'] = tokens[1][0][0]['size']
if len(tokens[1]) > 1 and tokens[1][1] == '...':
converted_type['size'].append(None)
tag = convert_tag(tokens[4 if is_named_element else 3])
if tag:
converted_type['element']['tag'] = tag
return converted_type
def convert_choice_type(_s, _l, tokens):
return {
'type': 'CHOICE',
'members': convert_members(tokens[2])
}
def convert_defined_type(_s, _l, tokens):
converted = {
'type': tokens[0]
}
# actual-parameters
if len(tokens) == 2:
converted.update(tokens[1])
return converted
def convert_integer_type(_s, _l, tokens):
tokens = tokens.asList()
compiled = {'type': 'INTEGER'}
if tokens[1]:
compiled['named-numbers'] = {
item[0]: item[2] for item in tokens[1]
}
return compiled
def convert_real_type(_s, _l, _tokens):
return {'type': 'REAL'}
def convert_enumerated_type(string, location, tokens):
return {
'type': 'ENUMERATED',
'values': convert_enum_values(string, location, tokens[2])
}
def convert_keyword_type(_s, _l, tokens):
return {
'type': tokens[0]
}
def convert_print(_s, _l, tokens):
print('convert_print', tokens)
def convert_object_identifier_type(_s, _l, _tokens):
return {
'type': 'OBJECT IDENTIFIER'
}
def convert_bit_string_type(_s, _l, tokens):
converted_type = {
'type': 'BIT STRING'
}
named_bit_list = tokens.asList()[1]
if named_bit_list:
converted_type['named-bits'] = [
tuple(named_bit) for named_bit in named_bit_list
]
return converted_type
def convert_octet_string_type(_s, _l, _tokens):
return {
'type': 'OCTET STRING'
}
def convert_ia5_string_type(_s, _l, _tokens):
return {
'type': 'IA5String'
}
def convert_any_defined_by_type(_s, _l, tokens):
return {
'type': 'ANY DEFINED BY',
'value': tokens[1],
'choices': {}
}
def convert_actual_parameter_list(_s, _l, tokens):
tokens = tokens.asList()[0]
converted = []
for parameter in tokens:
converted.append(parameter[0][0])
if converted:
converted = {'actual-parameters': converted}
else:
converted = None
return converted
def convert_parameter_list(_s, _l, tokens):
tokens = tokens.asList()
if tokens[0]:
converted = {'parameters': tokens[0]}
else:
converted = None
return converted
def convert_null_type(_s, _l, _tokens):
return {
'type': 'NULL'
}
def convert_boolean_type(_s, _l, _tokens):
return {
'type': 'BOOLEAN'
}
def convert_type(tokens, parameters):
converted_type, constraints = tokens
restricted_to = []
for constraint_tokens in constraints:
if isinstance(constraint_tokens, ParseResults):
constraint_tokens = constraint_tokens.asList()
if constraint_tokens == '...':
if restricted_to:
restricted_to.append(EXTENSION_MARKER)
if 'size' in converted_type:
converted_type['size'].append(None)
elif len(constraint_tokens) == 1:
if not isinstance(constraint_tokens[0], dict):
restricted_to.append(convert_number(constraint_tokens[0]))
elif 'size' in constraint_tokens[0]:
converted_type.update(constraint_tokens[0])
elif 'from' in constraint_tokens[0]:
converted_type.update(constraint_tokens[0])
elif 'with-components' in constraint_tokens[0]:
converted_type.update(constraint_tokens[0])
if isinstance(parameters, dict):
converted_type.update(parameters)
if '{' in restricted_to:
restricted_to = []
if restricted_to:
converted_type['restricted-to'] = restricted_to
types = [
'BIT STRING',
'OCTET STRING',
'IA5String',
'BMPString',
'VisibleString',
'UTF8String',
'NumericString',
'PrintableString'
]
if converted_type['type'] in types:
size = convert_size(constraints)
if size:
converted_type['size'] = size
if '&' in converted_type['type']:
converted_type['table'] = convert_table(tokens.asList()[1:])
return converted_type
def convert_bstring(_s, _l, tokens):
return '0b' + re.sub(r"[\sB']", '', tokens[0])
def convert_hstring(_s, _l, tokens):
return '0x' + re.sub(r"[\sH']", '', tokens[0]).lower()
def convert_bit_string_value(tokens):
value = tokens[0]
if value == 'IdentifierList':
value = value[:]
elif isinstance(value, str):
value = value
else:
value = None
return value
def convert_value(tokens, type_=None):
if type_ == 'INTEGER':
value = int(tokens[0])
elif type_ == 'OBJECT IDENTIFIER':
value = []
for value_tokens in tokens:
if len(value_tokens) == 2:
value.append((value_tokens[0], int(value_tokens[1])))
else:
value.append(convert_number(value_tokens[0]))
elif type_ == 'BOOLEAN':
value = (tokens[0] == 'TRUE')
elif tokens[0] == 'BitStringValue':
value = convert_bit_string_value(tokens[0])
elif isinstance(tokens[0], str):
value = convert_number(tokens[0])
elif isinstance(tokens[0], int):
value = tokens[0]
else:
value = None
return value
def convert_parameterized_object_set_assignment(_s, _l, tokens):
members = []
try:
for member_tokens in tokens[4].asList():
if len(member_tokens[0]) == 1:
member = member_tokens[0][0]
else:
member = {}
for item_tokens in member_tokens[0]:
name = item_tokens[0]
value = item_tokens[1][0]
if isinstance(value, Tokens):
value = value[0]
member[name] = convert_number(value)
members.append(member)
except (IndexError, KeyError):
pass
converted_type = {
'class': tokens[1],
'members': members
}
return ('parameterized-object-set-assignment',
tokens[0],
converted_type)
def convert_parameterized_object_assignment(_s, _l, tokens):
type_ = tokens[1]
converted_type = {
'type': type_,
'value': None
}
return ('parameterized-object-assignment',
tokens[0],
converted_type)
def convert_parameterized_object_class_assignment(s, loc, tokens):
members = []
for member in tokens[3]:
# Not an object class definition, for example a parameterized
# type assignment. Let other alternatives match it.
if not isinstance(member, (Tokens, ParseResults, list)):
raise ParseException(s, loc, 'Not an object class assignment.')
if member[0][1].islower():
converted_member = member[1][0]
if isinstance(converted_member, Tokens):
converted_member = converted_member[0]
else:
converted_member = {'type': 'OpenType'}
converted_member['name'] = member[0]
members.append(converted_member)
converted_type = {
'members': members
}
return ('parameterized-object-class-assignment',
tokens[0],
converted_type)
def convert_parameterized_type_assignment(_s, _l, tokens):
tokens = tokens.asList()
converted_type = convert_type(tokens[4], tokens[1])
try:
tag = convert_tag(tokens[3])
except ValueError:
tag = None
if tag:
converted_type['tag'] = tag
return ('parameterized-type-assignment',
tokens[0],
converted_type)
def convert_parameterized_value_assignment(_s, _l, tokens):
type_ = tokens[1][0][0]
if isinstance(type_, Tokens):
type_ = type_[0]
elif isinstance(type_, dict):
type_ = type_['type']
converted_type = {
'type': type_,
'value': convert_value(tokens[2], type_)
}
return ('parameterized-value-assignment',
tokens[0],
converted_type)
def convert_imports(_s, _l, tokens):
tokens = tokens.asList()
imports = {}
if tokens:
for from_tokens in tokens:
from_name = from_tokens[2]
LOGGER.debug("Converting imports from '%s'.", from_name)
imported = from_tokens[0]
if from_name in imports:
imported = list(set(imports[from_name] + imported))
imports[from_name] = sorted(imported)
return {'imports': imports}
def convert_assignment_list(_s, _l, tokens):
types = {}
values = {}
object_classes = {}
object_sets = {}
for kind, name, value in tokens:
if kind == 'parameterized-object-set-assignment':
if name in object_sets:
LOGGER.warning("Object set '%s' already defined.", name)
object_sets[name] = value
elif kind == 'parameterized-object-assignment':
if name in values:
LOGGER.warning("Object '%s' already defined.", name)
values[name] = value
elif kind == 'parameterized-object-class-assignment':
if name in object_classes:
LOGGER.warning("Object class '%s' already defined.", name)
object_classes[name] = value
elif kind == 'parameterized-type-assignment':
if name in types:
LOGGER.warning("Type '%s' already defined.", name)
types[name] = value
elif kind == 'parameterized-value-assignment':
if name in values:
LOGGER.warning("Value '%s' already defined.", name)
values[name] = value
else:
raise InternalParserError(
'Unrecognized assignment kind {}.'.format(kind))
return {
'types': types,
'values': values,
'object-classes': object_classes,
'object-sets': object_sets
}
def convert_module_body(_s, _l, tokens):
return merge_dicts(tokens)
def convert_module_definition(_s, _l, tokens):
tokens = tokens.asList()
module = tokens[1][0]
module['extensibility-implied'] = (tokens[0][3] != [])
if tokens[0][2]:
module['tags'] = tokens[0][2][0]
return {tokens[0][0]: module}
def convert_specification(_s, _l, tokens):
return merge_dicts(tokens)
def create_grammar():
"""Return the ASN.1 grammar as Pyparsing objects.
"""
# Keywords.
SEQUENCE = Keyword('SEQUENCE').set_name('SEQUENCE')
CHOICE = Keyword('CHOICE').set_name('CHOICE')
ENUMERATED = Keyword('ENUMERATED').set_name('ENUMERATED')
DEFINITIONS = Keyword('DEFINITIONS').set_name('DEFINITIONS')
BEGIN = Keyword('BEGIN').set_name('BEGIN')
END = Keyword('END').set_name('END')
AUTOMATIC = Keyword('AUTOMATIC').set_name('AUTOMATIC')
TAGS = Keyword('TAGS').set_name('TAGS')
OPTIONAL = Keyword('OPTIONAL').set_name('OPTIONAL')
OF = Keyword('OF').set_name('OF')
SIZE = Keyword('SIZE').set_name('SIZE')
INTEGER = Keyword('INTEGER').set_name('INTEGER')
REAL = Keyword('REAL').set_name('REAL')
BIT_STRING = Keyword('BIT STRING').set_name('BIT STRING')
OCTET_STRING = Keyword('OCTET STRING').set_name('OCTET STRING')
DEFAULT = Keyword('DEFAULT').set_name('DEFAULT')
IMPORTS = Keyword('IMPORTS').set_name('IMPORTS')
EXPORTS = Keyword('EXPORTS').set_name('EXPORTS')
FROM = Keyword('FROM').set_name('FROM')
CONTAINING = Keyword('CONTAINING').set_name('CONTAINING')
ENCODED_BY = Keyword('ENCODED_BY').set_name('ENCODED_BY')
IMPLICIT = Keyword('IMPLICIT').set_name('IMPLICIT')
EXPLICIT = Keyword('EXPLICIT').set_name('EXPLICIT')
OBJECT_IDENTIFIER = Keyword('OBJECT IDENTIFIER').set_name('OBJECT IDENTIFIER')
UNIVERSAL = Keyword('UNIVERSAL').set_name('UNIVERSAL')
APPLICATION = Keyword('APPLICATION').set_name('APPLICATION')
PRIVATE = Keyword('PRIVATE').set_name('PRIVATE')
SET = Keyword('SET').set_name('SET')
ANY_DEFINED_BY = Keyword('ANY DEFINED BY').set_name('ANY DEFINED BY')
EXTENSIBILITY_IMPLIED = Keyword('EXTENSIBILITY IMPLIED').set_name(
'EXTENSIBILITY IMPLIED')
BOOLEAN = Keyword('BOOLEAN').set_name('BOOLEAN')
TRUE = Keyword('TRUE').set_name('TRUE')
FALSE = Keyword('FALSE').set_name('FALSE')
CLASS = Keyword('CLASS').set_name('CLASS')
WITH_SYNTAX = Keyword('WITH SYNTAX').set_name('WITH SYNTAX')
UNIQUE = Keyword('UNIQUE').set_name('UNIQUE')
NULL = Keyword('NULL').set_name('NULL')
WITH_COMPONENT = Keyword('WITH COMPONENT').set_name('WITH COMPONENT')
WITH_COMPONENTS = Keyword('WITH COMPONENTS').set_name('WITH COMPONENTS')
WITH_SUCCESSORS = Keyword('WITH SUCCESSORS').set_name('WITH SUCCESSORS')
WITH_DESCENDANTS = Keyword('WITH DESCENDANTS').set_name('WITH DESCENDANTS')
COMPONENTS_OF = Keyword('COMPONENTS OF').set_name('COMPONENTS OF')
PRESENT = Keyword('PRESENT').set_name('PRESENT')
ABSENT = Keyword('ABSENT').set_name('ABSENT')
ALL = Keyword('ALL').set_name('ALL')
EXCEPT = Keyword('EXCEPT').set_name('EXCEPT')
MIN = Keyword('MIN').set_name('MIN')
MAX = Keyword('MAX').set_name('MAX')
INCLUDES = Keyword('INCLUDES').set_name('INCLUDES')
PATTERN = Keyword('PATTERN').set_name('PATTERN')
CONSTRAINED_BY = Keyword('CONSTRAINED BY').set_name('CONSTRAINED BY')
UNION = Keyword('UNION').set_name('UNION')
INTERSECTION = Keyword('INTERSECTION').set_name('INTERSECTION')
PLUS_INFINITY = Keyword('PLUS-INFINITY').set_name('PLUS-INFINITY')
MINUS_INFINITY = Keyword('MINUS-INFINITY').set_name('MINUS-INFINITY')
BMPString = Keyword('BMPString').set_name('BMPString')
GeneralString = Keyword('GeneralString').set_name('GeneralString')
GraphicString = Keyword('GraphicString').set_name('GraphicString')
IA5String = Keyword('IA5String').set_name('IA5String')
ISO646String = Keyword('ISO646String').set_name('ISO646String')
NumericString = Keyword('NumericString').set_name('NumericString')
PrintableString = Keyword('PrintableString').set_name('PrintableString')
TeletexString = Keyword('TeletexString').set_name('TeletexString')
UTCTime = Keyword('UTCTime').set_name('UTCTime')
GeneralizedTime = Keyword('GeneralizedTime').set_name('GeneralizedTime')
T61String = Keyword('T61String').set_name('T61String')
UniversalString = Keyword('UniversalString').set_name('UniversalString')
UTF8String = Keyword('UTF8String').set_name('UTF8String')
VideotexString = Keyword('VideotexString').set_name('VideotexString')
VisibleString = Keyword('VisibleString').set_name('VisibleString')
CHARACTER_STRING = Keyword('CHARACTER STRING').set_name('CHARACTER STRING')
# Various literals.
word = Word(printables, exclude_chars=',(){}[].:=;"|').set_name('word')
identifier = Regex(r'[a-z][a-zA-Z0-9-]*').set_name('identifier')
assign = Literal('::=').set_name('::=')
left_parenthesis = Literal('(')
right_parenthesis = Literal(')')
left_brace = Literal('{')
right_brace = Literal('}')
left_bracket = Literal('[')
right_bracket = Literal(']')
left_version_brackets = Literal('[[')
right_version_brackets = Literal(']]')
colon = Literal(':')
semi_colon = Literal(';')
dot = Literal('.')
range_separator = Literal('..')
ellipsis = Literal('...')
pipe = Literal('|')
caret = Literal('^')
comma = Literal(',')
at = Literal('@')
exclamation_mark = Literal('!')
integer = Word(nums + '-')
real_number = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?')
bstring = Regex(r"'[01\s]*'B")
hstring = Regex(r"'[0-9A-F\s]*'H")
cstring = QuotedString('"')
number = (Word(nums).set_name('number') + ~dot)
ampersand = Literal('&')
less_than = Literal('<')
reserved_words = Regex(r'(END|SEQUENCE|ENUMERATED|WITH)(\s|$)')
# Forward declarations.
value = Forward()
type_ = Forward()
object_ = Forward()
object_set = Forward()
primitive_field_name = Forward()
constraint = Forward()
element_set_spec = Forward()
token_or_group_spec = Forward()
value_reference = Forward().set_name('valuereference')
type_reference = Forward().set_name('typereference')
value_set = Forward().set_name('"valueSet" not implemented')
named_type = Forward()
root_element_set_spec = Forward()
defined_object_set = Forward()
syntax_list = Forward()
object_from_object = Forward()
object_set_from_objects = Forward()
defined_value = Forward().set_name('DefinedValue')
component_type_lists = Forward()
extension_and_exception = Forward()
optional_extension_marker = Forward()
additional_element_set_spec = Forward()
reference = Forward()
defined_object_class = Forward()
defined_type = Forward()
module_reference = Forward()
external_type_reference = Forward()
external_value_reference = Forward()
simple_defined_type = Forward()
defined_object = Forward()
referenced_value = Forward()
builtin_value = Forward()
named_value = Forward()
sequence_value = Forward()
signed_number = Forward()
name_and_number_form = Forward()
number_form = Forward().set_name('numberForm')
definitive_number_form = Forward().set_name('definitiveNumberForm')
version_number = Forward()
union_mark = Forward()
named_number = Forward()
size_constraint = Forward()
value_field_reference = Combine(ampersand + value_reference)
type_field_reference = Combine(ampersand + type_reference)
# ToDo: Remove size_paren as they are a workaround for
# SEQUENCE/SET OF.
size_paren = (Suppress(Optional(left_parenthesis))
+ size_constraint
+ Suppress(Optional(right_parenthesis)))
class_number = (number | defined_value).set_name('ClassNumber')
tag = Group(Optional(Suppress(left_bracket)
- Group(Optional(UNIVERSAL
| APPLICATION
| PRIVATE)
+ class_number)
- Suppress(right_bracket)
+ Group(Optional(IMPLICIT | EXPLICIT))))
any_defined_by_type = (ANY_DEFINED_BY + word)
any_defined_by_type.set_name('ANY DEFINED BY')
identifier_list = DelimitedList(identifier)
# X.683: 8. Parameterized assignments
dummy_reference = reference
dummy_governor = dummy_reference
governor = (type_ | defined_object_class)
param_governor = (governor | dummy_governor)
parameter = (Suppress(Optional(param_governor + colon)) + dummy_reference)
parameter_list = Group(Optional(Suppress(left_brace)
+ DelimitedList(parameter)
+ Suppress(right_brace)))
# X.683: 9. Referencing parameterized definitions
actual_parameter = Group(type_
| value
| value_set
| defined_object_class
| object_
| object_set)
actual_parameter_list = Group(Suppress(left_brace)
+ DelimitedList(actual_parameter)
+ Suppress(right_brace))
parameterized_object = (defined_object + actual_parameter_list)
parameterized_object_set = (defined_object_set + actual_parameter_list)
parameterized_object_class = (defined_object_class + actual_parameter_list)
parameterized_value_set_type = (simple_defined_type
+ actual_parameter_list)
simple_defined_value = (external_value_reference
| value_reference)
parameterized_value = (simple_defined_value
+ actual_parameter_list)
simple_defined_type <<= (external_type_reference
| type_reference)
parameterized_type = (simple_defined_type
+ actual_parameter_list)
parameterized_reference = (reference + Optional(left_brace + right_brace))
# X.682: 11. Contents constraints
contents_constraint = ((CONTAINING + type_)
| (ENCODED_BY + value)
| (CONTAINING + type_ + ENCODED_BY + value))
# X.682: 10. Table constraints, including component relation constraints
level = OneOrMore(dot)
component_id_list = identifier
at_notation = (Suppress(at)
- (component_id_list
| Combine(level + component_id_list)))
component_relation_constraint = (left_brace
+ Group(Group(defined_object_set))
+ right_brace
+ left_brace
- Group(DelimitedList(at_notation))
- right_brace)
component_relation_constraint.set_name('"{"')
simple_table_constraint = object_set
table_constraint = (component_relation_constraint
| simple_table_constraint)
# X.682: 9. User-defined constants
user_defined_constraint_parameter = ((governor
+ colon
+ (value
| value_set
| object_
| object_set))
| type_
| defined_object_class)
user_defined_constraint = (CONSTRAINED_BY
- left_brace
- Optional(DelimitedList(
user_defined_constraint_parameter))
- right_brace)
user_defined_constraint.set_name('CONSTRAINED_BY')
# X.682: 8. General constraint specification
general_constraint = (user_defined_constraint
| table_constraint
| contents_constraint)
# X.681: 7. ASN.1 lexical items
object_set_reference = type_reference
value_set_field_reference = NoMatch().set_name(
'"valueSetFieldReference" not implemented')
object_field_reference = NoMatch().set_name(
'"objectFieldReference" not implemented')
object_set_field_reference = NoMatch().set_name(
'"objectSetFieldReference" not implemented')
object_class_reference = (NotAny(reserved_words)
+ Regex(r'[A-Z][A-Z0-9-]*'))
object_reference = value_reference
# X.681: 8. Referencing definitions
external_object_set_reference = NoMatch().set_name(
'"externalObjectSetReference" not implemented')
defined_object_set <<= (external_object_set_reference
| object_set_reference)
defined_object <<= NoMatch().set_name('"definedObject" not implemented')
defined_object_class <<= object_class_reference
# X.681: 9. Information object class definition and assignment
field_name = primitive_field_name
primitive_field_name <<= (type_field_reference
| value_field_reference
| value_set_field_reference
| object_field_reference
| object_set_field_reference)
object_set_field_spec = NoMatch().set_name('"objectSetFieldSpec" not implemented')
object_field_spec = NoMatch().set_name('"objectFieldSpec" not implemented')
variable_type_value_set_field_spec = NoMatch().set_name(
'"variableTypeValueSetFieldSpec" not implemented')
fixed_type_value_set_field_spec = NoMatch().set_name(
'"fixedTypeValueSetFieldSpec" not implemented')
variable_type_value_field_spec = NoMatch().set_name(
'"variableTypeValueFieldSpec" not implemented')
fixed_type_value_field_spec = (value_field_reference
+ type_
+ Optional(UNIQUE)
+ Optional(OPTIONAL
| (DEFAULT - value)))
type_field_spec = (type_field_reference
+ Optional(OPTIONAL
| (DEFAULT - type_)))
field_spec = Group(type_field_spec
| fixed_type_value_field_spec
| variable_type_value_field_spec
| fixed_type_value_set_field_spec
| variable_type_value_set_field_spec
| object_field_spec
| object_set_field_spec)
with_syntax_spec = (WITH_SYNTAX - syntax_list)
object_class_defn = (CLASS
- Suppress(left_brace)
- Group(DelimitedList(field_spec))
- Suppress(right_brace)
- Optional(with_syntax_spec))
object_class = (object_class_defn
# | defined_object_class
| parameterized_object_class)
parameterized_object_class_assignment = (object_class_reference
+ Suppress(parameter_list)
+ assign
+ object_class)
# X.681: 10. Syntax list
literal = (word | comma)
required_token = (literal | primitive_field_name)
optional_group = (left_bracket
+ OneOrMore(token_or_group_spec)
+ right_bracket)
token_or_group_spec <<= (required_token | optional_group)
syntax_list <<= (left_brace
+ OneOrMore(token_or_group_spec)
+ right_brace)
# X.681: 11. Information object definition and assignment
setting = (type_ | value | value_set | object_ | object_set | QuotedString('"'))
field_setting = Group(primitive_field_name + setting)
default_syntax = (Suppress(left_brace)
+ DelimitedList(field_setting)
+ Suppress(right_brace))
defined_syntax_token = (literal | setting)
defined_syntax = (left_brace + ZeroOrMore(defined_syntax_token) + right_brace)
object_defn = Group(default_syntax | defined_syntax)
object_ <<= (defined_object
| object_defn
| object_from_object
| parameterized_object)
parameterized_object_assignment = (object_reference
+ Suppress(parameter_list)
+ defined_object_class
+ Suppress(assign)
+ object_)
# X.681: 12. Information object set definition and assignment
object_set_elements = (object_
| defined_object_set
| object_set_from_objects
| parameterized_object_set)
object_set_spec = ((root_element_set_spec
+ Optional(comma
+ ellipsis
+ Optional(comma
+ additional_element_set_spec)))
| (ellipsis + Optional(comma + additional_element_set_spec)))
object_set <<= (left_brace + Group(object_set_spec) + right_brace)
object_set.set_name('"{"')
parameterized_object_set_assignment = (object_set_reference
+ Suppress(parameter_list)
+ defined_object_class
- assign
- object_set)
# X.681: 13. Associated tables
# X.681: 14. Notation for the object class field type
fixed_type_field_val = (builtin_value | referenced_value)
open_type_field_val = (type_ + colon + value)
object_class_field_value = (open_type_field_val
| fixed_type_field_val)
object_class_field_type = Combine(defined_object_class
+ dot
+ field_name)
object_class_field_type.set_name('ObjectClassFieldType')
# X.681: 15. Information from objects
object_set_from_objects <<= NoMatch().set_name(
'"objectSetFromObjects" not implemented')
object_from_object <<= NoMatch().set_name('"objectFromObject" not implemented')
# X.680: 49. The exception identifier
exception_spec = Optional(
exclamation_mark
+ NoMatch().set_name('"exceptionSpec" not implemented'))
# X.680: 47. Subtype elements
pattern_constraint = (PATTERN + value)
value_constraint = constraint
presence_constraint = (PRESENT | ABSENT | OPTIONAL)
component_constraint = (Optional(value_constraint)
+ Optional(presence_constraint))
named_constraint = Group(identifier + component_constraint)
type_constraints = DelimitedList(named_constraint)
full_specification = (left_brace + Group(type_constraints) + right_brace)
partial_specification = (left_brace
+ Group(ellipsis
+ Suppress(comma)
+ type_constraints)
+ right_brace)
single_type_constraint = constraint
multiple_type_constraints = (full_specification | partial_specification)
with_component = WITH_COMPONENT - single_type_constraint
with_components = WITH_COMPONENTS - multiple_type_constraints
inner_type_constraints = with_component | with_components
permitted_alphabet = (FROM - constraint)
type_constraint = type_
size_constraint <<= (SIZE - Group(constraint))
upper_end_value = (value | MAX)
lower_end_value = (value | MIN)
upper_endpoint = (Optional(less_than) + upper_end_value)
lower_endpoint = (lower_end_value + Optional(less_than))
value_range = (((Combine(integer + dot) + Suppress(range_separator))
| (integer + Suppress(range_separator))
| (lower_endpoint + Suppress(range_separator)))
- upper_endpoint)
contained_subtype = (Optional(INCLUDES) + type_)
single_value = value
subtype_elements = (size_constraint
| permitted_alphabet
| value_range
| inner_type_constraints
| single_value
| pattern_constraint
| contained_subtype
| type_constraint)
# X.680: 46. Element set specification
union_mark <<= (pipe | UNION)
intersection_mark = (caret | INTERSECTION)
elements = Group(subtype_elements
| object_set_elements
| (left_parenthesis + element_set_spec + right_parenthesis))
unions = DelimitedList(elements, delim=(union_mark | intersection_mark))
exclusions = (EXCEPT + elements)
element_set_spec <<= (Suppress(ALL + exclusions) | unions)
root_element_set_spec <<= element_set_spec
additional_element_set_spec <<= element_set_spec
element_set_specs = (root_element_set_spec
+ Optional(Suppress(comma) - ellipsis
+ Optional(Suppress(comma)
- additional_element_set_spec)))
# X.680: 45. Constrained types
subtype_constraint = element_set_specs
constraint_spec = (general_constraint
| subtype_constraint)
constraint_spec.set_name('one or more constraints')
constraint <<= (Suppress(left_parenthesis)
- constraint_spec
- Suppress(right_parenthesis))
# X.680: 40. Definition of unrestricted character string types
unrestricted_character_string_type = CHARACTER_STRING
unrestricted_character_string_value = NoMatch().set_name(
'"unrestrictedCharacterStringValue" not implemented')
# X.680: 39. Canonical order of characters
# X.680: 38. Specification of the ASN.1 module "ASN.1-CHARACTER-MODULE"
# X.680: 37. Definition of restricted character string types
group = number
plane = number
row = number
cell = number
quadruple = (left_brace
+ group + comma
+ plane + comma
+ row + comma
+ cell
+ right_brace)
table_column = number
table_row = number
tuple_ = (left_brace + table_column + comma + table_row + right_brace)
chars_defn = (cstring | quadruple | tuple_ | defined_value)
charsyms = DelimitedList(chars_defn)
character_string_list = (left_brace + charsyms + right_brace)
restricted_character_string_value = (cstring
| character_string_list
| quadruple
| tuple_)
restricted_character_string_type = (BMPString
| GeneralString
| GraphicString
| IA5String
| ISO646String
| NumericString
| PrintableString
| TeletexString
| UTCTime
| GeneralizedTime
| T61String
| UniversalString
| UTF8String
| VideotexString
| VisibleString)
# X.680: 36. Notation for character string types
character_string_value = (restricted_character_string_value
| unrestricted_character_string_value)
character_string_type = (restricted_character_string_type
| unrestricted_character_string_type)
# X.680: 35. The character string types
# X.680: 34. Notation for the external type
# external_value = sequence_value
# X.680: 33. Notation for embedded-pdv type
# embedded_pdv_value = sequence_value
# X.680: 32. Notation for relative object identifier type
relative_oid_components = Group(number_form
| name_and_number_form
| defined_value)
relative_oid_component_list = OneOrMore(relative_oid_components)
relative_oid_value = (Suppress(left_brace)
+ relative_oid_component_list
+ Suppress(right_brace))
# X.680: 31. Notation for object identifier type
name_and_number_form <<= (identifier
+ Suppress(left_parenthesis)
- number_form
- Suppress(right_parenthesis))
number_form <<= (number | defined_value)
name_form = identifier
obj_id_components = Group(name_and_number_form
| defined_value
| number_form
| name_form)
obj_id_components_list = OneOrMore(obj_id_components)
object_identifier_value = ((Suppress(left_brace)
+ obj_id_components_list
+ Suppress(right_brace))
| (Suppress(left_brace)
+ defined_value
+ obj_id_components_list
+ Suppress(right_brace)))
object_identifier_type = (OBJECT_IDENTIFIER
+ Optional(left_parenthesis
+ DelimitedList(word, delim='|')
+ right_parenthesis))
object_identifier_type.set_name('OBJECT IDENTIFIER')
# X.680: 30. Notation for tagged types
tagged_value = NoMatch()
# X.680: 29. Notation for selection types
# X.680: 28. Notation for the choice types
alternative_type_list = DelimitedList(named_type)
extension_addition_alternatives_group = Group(left_version_brackets
+ Suppress(version_number)
- Group(alternative_type_list)
- right_version_brackets)
extension_addition_alternative = (extension_addition_alternatives_group
| named_type)
extension_addition_alternatives_list = DelimitedList(extension_addition_alternative)
extension_addition_alternatives = Optional(Suppress(comma)
+ extension_addition_alternatives_list)
root_alternative_type_list = alternative_type_list
alternative_type_lists = (root_alternative_type_list
+ Optional(Suppress(comma)
+ extension_and_exception
+ extension_addition_alternatives
+ optional_extension_marker))
choice_type = (CHOICE
- left_brace
+ Group(alternative_type_lists)
- right_brace)
choice_type.set_name('CHOICE')
choice_value = (identifier + colon + value)
# X.680: 27. Notation for the set-of types
# set_of_value = NoMatch()
set_of_type = (SET
+ Group(Optional(Group(size_constraint) | constraint))
+ OF
+ Optional(identifier)
- tag
- type_)
set_of_type.set_name('SET OF')
# X.680: 26. Notation for the set types
# set_value = NoMatch()
set_type = (SET
+ left_brace
+ Group(Optional(component_type_lists
| (extension_and_exception
+ optional_extension_marker)))
- right_brace)
set_type.set_name('SET')
# X.680: 25. Notation for the sequence-of types
sequence_of_value = NoMatch()
sequence_of_type = (SEQUENCE
+ Group(Optional(Group(size_constraint) | constraint))
+ OF
+ Optional(identifier)
- tag
- type_)
sequence_of_type.set_name('SEQUENCE OF')
# X.680: 24. Notation for the sequence types
component_value_list = DelimitedList(named_value)
sequence_value <<= (left_brace
+ Optional(component_value_list)
+ right_brace)
component_type = Group(named_type
+ Group(Optional(OPTIONAL
| (DEFAULT + value)))
| (COMPONENTS_OF - type_))
version_number <<= Optional(number + Suppress(colon))
extension_addition_group = Group(left_version_brackets
+ Suppress(version_number)
+ Group(DelimitedList(component_type))
+ right_version_brackets)
extension_and_exception <<= (ellipsis + Optional(exception_spec))
extension_addition = (component_type | extension_addition_group)
extension_addition_list = DelimitedList(extension_addition)
extension_additions = Optional(Suppress(comma) + extension_addition_list)
extension_end_marker = (Suppress(comma) + ellipsis)
optional_extension_marker <<= Optional(Suppress(comma) + ellipsis)
component_type_list = DelimitedList(component_type)
root_component_type_list = component_type_list
component_type_lists <<= ((root_component_type_list
+ Optional(Suppress(comma)
+ extension_and_exception
+ extension_additions
+ ((extension_end_marker
+ Suppress(comma)
+ root_component_type_list)
| optional_extension_marker)))
| (extension_and_exception
+ extension_additions
+ ((extension_end_marker
+ Suppress(comma)
+ root_component_type_list)
| optional_extension_marker)))
sequence_type = (SEQUENCE
- left_brace
+ Group(Optional(component_type_lists
| (extension_and_exception
+ optional_extension_marker)))
- right_brace)
sequence_type.set_name('SEQUENCE')
# X.680: 23. Notation for the null type
null_value = NULL
null_type = NULL
# X.680: 22. Notation for the octetstring type
# octet_string_value = (bstring
# | hstring
# | (CONTAINING + value))
octet_string_type = OCTET_STRING
octet_string_type.set_name('OCTET STRING')
# X.680: 21. Notation for the bitstring type
bit_string_type = (BIT_STRING
+ Group(Optional(
Suppress(left_brace)
+ DelimitedList(Group(word
+ Suppress(left_parenthesis)
+ word
+ Suppress(right_parenthesis)))
+ Suppress(right_brace))))
bit_string_type.set_name('BIT STRING')
bit_string_value = Tag('BitStringValue',
bstring
| hstring
| Tag('IdentifierList',
Suppress(left_brace)
+ Optional(identifier_list)
+ Suppress(right_brace))
| (CONTAINING - value))
# X.680: 20. Notation for the real type
special_real_value = (PLUS_INFINITY
| MINUS_INFINITY)
numeric_real_value = (real_number
| sequence_value)
real_value = (numeric_real_value
| special_real_value)
real_type = REAL
real_type.set_name('REAL')
# X.680: 19. Notation for the enumerated type
enumerated_value = identifier
enumeration_item = (named_number | identifier)
enumeration = DelimitedList(enumeration_item)
root_enumeration = enumeration
additional_enumeration = enumeration
enumerations = Group(Group(root_enumeration)
+ Group(Optional(Group(Suppress(comma
- ellipsis
+ exception_spec))
+ Optional(Suppress(comma)
- additional_enumeration))))
enumerated_type = (ENUMERATED
- left_brace
+ enumerations
- right_brace)
enumerated_type.set_name('ENUMERATED')
# X.680: 18. Notation for the integer type
integer_value = (signed_number | identifier)
signed_number <<= Combine(Optional('-') + number)
named_number <<= Group(identifier
+ left_parenthesis
+ (signed_number | defined_value)
+ right_parenthesis)
named_number_list = DelimitedList(named_number)
integer_type = (INTEGER
+ Group(Optional(Suppress(left_brace)
+ named_number_list
+ Suppress(right_brace))))
integer_type.set_name('INTEGER')
# X.680: 17. Notation for boolean type
boolean_type = BOOLEAN
boolean_value = (TRUE | FALSE)
# X.680: 16. Definition of types and values
named_value <<= (identifier + value)
referenced_value <<= NoMatch().set_name('"referencedValue" not implemented')
builtin_value <<= (bit_string_value
| boolean_value
| character_string_value
| choice_value
| relative_oid_value
| sequence_value
# | embedded_pdv_value
| enumerated_value
# | external_value
# | instance_of_value
| real_value
| integer_value
| null_value
| object_identifier_value
# | octet_string_value
| sequence_of_value
# | set_value
# | set_of_value
| tagged_value)
value <<= Group(object_class_field_value)
# | referenced_value
# | builtin_value)
named_type <<= Group(identifier
- tag
- type_)
referenced_type = defined_type
referenced_type.set_name('ReferencedType')
builtin_type = (choice_type
| integer_type
| null_type
| real_type
| bit_string_type
| octet_string_type
| enumerated_type
| sequence_of_type
| sequence_type
| object_class_field_type
| set_of_type
| set_type
| object_identifier_type
| boolean_type
| character_string_type)
type_ <<= Group((builtin_type
| any_defined_by_type
| referenced_type).set_name('Type')
+ Group(ZeroOrMore(constraint)))
# X.680: 15. Assigning types and values
type_reference <<= (NotAny(reserved_words)
+ Regex(r'[A-Z][a-zA-Z0-9-]*'))
value_reference <<= Regex(r'[a-z][a-zA-Z0-9-]*')
value_set <<= NoMatch().set_name('"valueSet" not implemented')
parameterized_type_assignment = (type_reference
+ parameter_list
- assign
- tag
- type_)
parameterized_value_assignment = (value_reference
+ Suppress(parameter_list)
- Group(type_)
- Suppress(assign)
- value)
# X.680: 14. Notation to support references to ASN.1 components
# X.680: 13. Referencing type and value definitions
external_value_reference <<= (module_reference
+ dot
+ value_reference)
external_type_reference <<= (module_reference
+ dot
+ type_reference)
defined_type <<= (external_type_reference
| parameterized_type
| parameterized_value_set_type
| type_reference)
defined_value <<= (external_value_reference
| parameterized_value
| value_reference)
# X.680: 12. Module definition
module_reference <<= (NotAny(reserved_words)
+ Regex(r'[A-Z][a-zA-Z0-9-]*').set_name('modulereference'))
assigned_identifier = Suppress(Optional(object_identifier_value
| (defined_value + ~(comma | FROM))))
global_module_reference = (module_reference + assigned_identifier)
reference <<= (type_reference
| value_reference
| object_class_reference
| object_reference
| object_set_reference)
symbol = (parameterized_reference
| reference)
symbol_list = Group(DelimitedList(symbol))
symbols_from_module = (symbol_list
+ FROM
+ global_module_reference
+ Suppress(Optional(WITH_SUCCESSORS
| WITH_DESCENDANTS)))
symbols_imported = ZeroOrMore(Group(symbols_from_module))
imports = Optional(Suppress(IMPORTS)
- symbols_imported
- Suppress(semi_colon))
symbols_exported = OneOrMore(symbol_list)
exports = Suppress(Optional(EXPORTS
- (ALL | symbols_exported) + semi_colon))
assignment = (parameterized_object_set_assignment
| parameterized_object_assignment
| parameterized_object_class_assignment
| parameterized_type_assignment
| parameterized_value_assignment)
assignment_list = ZeroOrMore(assignment)
module_body = (exports + imports + assignment_list)
definitive_name_and_number_form = (identifier
+ Suppress(left_parenthesis)
- definitive_number_form
- Suppress(right_parenthesis))
definitive_number_form <<= number
definitive_obj_id_component = Group(definitive_name_and_number_form
| name_form
| definitive_number_form)
definitive_obj_id_components_list = OneOrMore(definitive_obj_id_component)
definitive_identifier = Group(Optional(Suppress(left_brace)
- definitive_obj_id_components_list
- Suppress(right_brace)))
module_identifier = (module_reference
+ definitive_identifier)
tag_default = Group(Optional((AUTOMATIC | EXPLICIT | IMPLICIT) + TAGS))
extension_default = Group(Optional(EXTENSIBILITY_IMPLIED))
module_definition = (Group(module_identifier
- Suppress(DEFINITIONS)
+ tag_default
+ extension_default
- Suppress(assign)
- Suppress(BEGIN))
+ Group(module_body)
- Suppress(END))
# The whole specification.
specification = OneOrMore(module_definition) + StringEnd()
# Parse actions converting tokens to asn1tools representation.
integer.set_parse_action(convert_integer)
signed_number.set_parse_action(convert_integer)
real_number.set_parse_action(convert_real_number)
bstring.set_parse_action(convert_bstring)
hstring.set_parse_action(convert_hstring)
value_range.set_parse_action(convert_value_range)
with_component.set_parse_action(convert_inner_type_constraints)
with_components.set_parse_action(convert_inner_type_constraints)
size_constraint.set_parse_action(convert_size_constraint)
permitted_alphabet.set_parse_action(convert_permitted_alphabet)
constraint.set_parse_action(convert_constraint)
module_body.set_parse_action(convert_module_body)
specification.set_parse_action(convert_specification)
module_definition.set_parse_action(convert_module_definition)
assignment_list.set_parse_action(convert_assignment_list)
imports.set_parse_action(convert_imports)
parameterized_object_set_assignment.set_parse_action(
convert_parameterized_object_set_assignment)
parameterized_object_assignment.set_parse_action(
convert_parameterized_object_assignment)
parameterized_object_class_assignment.set_parse_action(
convert_parameterized_object_class_assignment)
parameterized_type_assignment.set_parse_action(
convert_parameterized_type_assignment)
parameterized_value_assignment.set_parse_action(
convert_parameterized_value_assignment)
sequence_type.set_parse_action(convert_sequence_type)
sequence_of_type.set_parse_action(convert_sequence_of_type)
set_type.set_parse_action(convert_set_type)
set_of_type.set_parse_action(convert_set_of_type)
integer_type.set_parse_action(convert_integer_type)
real_type.set_parse_action(convert_real_type)
boolean_type.set_parse_action(convert_boolean_type)
bit_string_type.set_parse_action(convert_bit_string_type)
octet_string_type.set_parse_action(convert_octet_string_type)
null_type.set_parse_action(convert_null_type)
object_identifier_type.set_parse_action(convert_object_identifier_type)
enumerated_type.set_parse_action(convert_enumerated_type)
choice_type.set_parse_action(convert_choice_type)
defined_type.set_parse_action(convert_defined_type)
character_string_type.set_parse_action(convert_keyword_type)
object_class_field_type.set_parse_action(convert_keyword_type)
any_defined_by_type.set_parse_action(convert_any_defined_by_type)
actual_parameter_list.set_parse_action(convert_actual_parameter_list)
parameter_list.set_parse_action(convert_parameter_list)
return specification
def ignore_comments(string):
"""Ignore comments in given string by replacing them with spaces. This
reduces the parsing time by roughly a factor of two.
"""
comments = [
(mo.start(), mo.group(0))
for mo in re.finditer(r'(/\*|\*/|--|\n)', string)
]
comments.sort()
in_single_line_comment = False
multi_line_comment_depth = 0
start_offset = 0
non_comment_offset = 0
chunks = []
for offset, kind in comments:
if in_single_line_comment:
if kind in ['--', '\n']:
in_single_line_comment = False
if kind == '--':
offset += 2
chunks.append(' ' * (offset - start_offset))
non_comment_offset = offset
elif multi_line_comment_depth > 0:
if kind == '/*':
multi_line_comment_depth += 1
elif kind == '*/':
multi_line_comment_depth -= 1
if multi_line_comment_depth == 0:
offset += 2
chunks.append(' ' * (offset - start_offset))
non_comment_offset = offset
elif kind == '--':
in_single_line_comment = True
start_offset = offset
chunks.append(string[non_comment_offset:start_offset])
elif kind == '/*':
multi_line_comment_depth = 1
start_offset = offset
chunks.append(string[non_comment_offset:start_offset])
if in_single_line_comment:
raise ParseSyntaxException(
string,
start_offset,
'Missing newline or -- for single line comment')
if multi_line_comment_depth > 0:
raise ParseSyntaxException(
string,
start_offset,
'Missing */ for multi line comment')
chunks.append(string[non_comment_offset:])
return ''.join(chunks)
def parse_string(string):
"""Parse given ASN.1 specification string and return a dictionary of
its contents.
The dictionary can later be compiled with
:func:`~asn1tools.compile_dict()`.
>>> with open('foo.asn') as fin:
... foo = asn1tools.parse_string(fin.read())
"""
grammar = create_grammar()
try:
string = ignore_comments(string)
tokens = grammar.parse_string(string).asList()
except (ParseException, ParseSyntaxException) as e:
raise ParseError("Invalid ASN.1 syntax at line {}, column {}: '{}': {}.".format(
e.lineno,
e.column,
e.mark_input_line(),
e.msg))
return tokens[0]
def parse_files(filenames, encoding='utf-8'):
"""Parse given ASN.1 specification file(s) and return a dictionary of
its/their contents.
The dictionary can later be compiled with
:func:`~asn1tools.compile_dict()`.
`encoding` is the text encoding. This argument is passed to the
built-in function `open()`.
>>> foo = asn1tools.parse_files('foo.asn')
"""
if isinstance(filenames, str):
filenames = [filenames]
string = ''
for filename in filenames:
if sys.version_info[0] < 3:
with open(filename, 'r') as fin:
string += fin.read()
string += '\n'
else:
with open(filename, 'r', encoding=encoding, errors='replace') as fin:
string += fin.read()
string += '\n'
return parse_string(string)
asn1tools-0.169.0/asn1tools/source/ 0000775 0000000 0000000 00000000000 15245442746 0017052 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/asn1tools/source/__init__.py 0000664 0000000 0000000 00000000032 15245442746 0021156 0 ustar 00root root 0000000 0000000 # Source code generators.
asn1tools-0.169.0/asn1tools/source/c/ 0000775 0000000 0000000 00000000000 15245442746 0017274 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/asn1tools/source/c/__init__.py 0000664 0000000 0000000 00000027612 15245442746 0021415 0 ustar 00root root 0000000 0000000 import time
from ...version import __version__
from . import oer
from . import uper
from .utils import camel_to_snake_case
HEADER_FMT = '''\
/**
* The MIT License (MIT)
*
* Copyright (c) 2018-2019 Erik Moqvist
*
* 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.
*/
/**
* This file was generated by asn1tools version {version} {date}.
*/
#ifndef {include_guard}
#define {include_guard}
#include
#include
#include
#ifndef ENOMEM
# define ENOMEM 12
#endif
#ifndef EINVAL
# define EINVAL 22
#endif
#ifndef EOUTOFDATA
# define EOUTOFDATA 500
#endif
#ifndef EBADCHOICE
# define EBADCHOICE 501
#endif
#ifndef EBADLENGTH
# define EBADLENGTH 502
#endif
#ifndef EBADENUM
# define EBADENUM 503
#endif
{structs}
{declarations}
#endif
'''
SOURCE_FMT = '''\
/**
* The MIT License (MIT)
*
* Copyright (c) 2018-2019 Erik Moqvist
*
* 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.
*/
/**
* This file was generated by asn1tools version {version} {date}.
*/
#include
#include "{header}"
{helpers}
{definitions}\
'''
FUZZER_SOURCE_FMT = '''\
/**
* The MIT License (MIT)
*
* Copyright (c) 2018-2019 Erik Moqvist
*
* 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.
*/
/**
* This file was generated by asn1tools version {version} {date}.
*/
#include
#include
#include
#include
#include
#include "{header}"
static void assert_first_encode(ssize_t res)
{{
if (res < 0) {{
printf("First encode failed with %ld.\\n", res);
__builtin_trap();
}}
}}
static void assert_second_decode(ssize_t res)
{{
if (res < 0) {{
printf("Second decode failed with %ld.\\n", res);
__builtin_trap();
}}
}}
static void assert_second_decode_data(const void *decoded_p,
const void *decoded2_p,
size_t size)
{{
if (memcmp(decoded_p, decoded2_p, size) != 0) {{
printf("Second decode data does not match first decoded data.\\n");
__builtin_trap();
}}
}}
static void assert_second_encode(ssize_t res, ssize_t res2)
{{
if (res != res2) {{
printf("Second encode result %ld does not match first pack "
"result %ld.\\n",
res,
res2);
__builtin_trap();
}}
}}
static void assert_second_encode_data(const uint8_t *encoded_p,
const uint8_t *encoded2_p,
ssize_t size)
{{
ssize_t i;
if (memcmp(encoded_p, encoded2_p, size) != 0) {{
for (i = 0; i < size; i++) {{
printf("[%04ld]: 0x%02x 0x%02x\\n", i, encoded_p[i], encoded2_p[i]);
}}
__builtin_trap();
}}
}}
{tests}
int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t size)
{{
{llvm_body}
return (0);
}}
'''
FUZZER_MAKEFILE_FMT = '''\
#
# The MIT License (MIT)
#
# Copyright (c) 2018-2019 Erik Moqvist
#
# 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.
#
#
# This file was generated by asn1tools version {version} {date}.
#
CC = clang
EXE = fuzzer
C_SOURCES = \\
\t{source} \\
\t{fuzzer_source}
CFLAGS = \\
\t-fprofile-instr-generate \\
\t-fcoverage-mapping \\
\t-I. \\
\t-g -fsanitize=address,fuzzer \\
\t-fsanitize=signed-integer-overflow \\
\t-fno-sanitize-recover=all
EXECUTION_TIME ?= 5
all:
\t$(CC) $(CFLAGS) $(C_SOURCES) -o $(EXE)
\trm -f $(EXE).profraw
\tLLVM_PROFILE_FILE="$(EXE).profraw" \\
\t ./$(EXE) \\
\t -max_total_time=$(EXECUTION_TIME)
\tllvm-profdata merge -sparse $(EXE).profraw -o $(EXE).profdata
\tllvm-cov show ./$(EXE) -instr-profile=$(EXE).profdata
\tllvm-cov report ./$(EXE) -instr-profile=$(EXE).profdata
'''
TEST_FMT = '''
static void test_{name}(
const uint8_t *encoded_p,
size_t size)
{{
ssize_t res;
ssize_t res2;
ssize_t i;
uint8_t encoded[size];
uint8_t encoded2[size];
struct {name}_t decoded;
struct {name}_t decoded2;
memset(&decoded, 0, sizeof(decoded));
res = {name}_decode(
&decoded,
encoded_p,
size);
if (res >= 0) {{
res = {name}_encode(
&encoded[0],
sizeof(encoded),
&decoded);
assert_first_encode(res);
memset(&decoded2, 0, sizeof(decoded2));
res2 = {name}_decode(
&decoded2,
&encoded[0],
res);
assert_second_decode(res2);
assert_second_decode_data(&decoded,
&decoded2,
sizeof(decoded));
res2 = {name}_encode(
&encoded2[0],
sizeof(encoded2),
&decoded);
assert_second_encode(res, res2);
assert_second_encode_data(&encoded[0], &encoded2[0], res);
}}
}}\
'''
def _generate_fuzzer_source(namespace,
compiled,
date,
header_name,
source_name,
fuzzer_source_name):
tests = []
calls = []
for module_name, module in sorted(compiled.modules.items()):
for type_name in sorted(module):
name = '{}_{}_{}'.format(namespace,
camel_to_snake_case(module_name),
camel_to_snake_case(type_name))
test = TEST_FMT.format(name=name)
tests.append(test)
call = ' test_{}(data_p, size);'.format(name)
calls.append(call)
source = FUZZER_SOURCE_FMT.format(version=__version__,
date=date,
header=header_name,
tests='\n'.join(tests),
llvm_body='\n'.join(calls))
makefile = FUZZER_MAKEFILE_FMT.format(version=__version__,
date=date,
source=source_name,
fuzzer_source=fuzzer_source_name)
return source, makefile
def generate(compiled,
codec,
namespace,
header_name,
source_name,
fuzzer_source_name):
"""Generate C source code from given compiled specification.
`namespace` is used as a prefix for all defines, data structures
and functions.
`header_name` is the file name of the C header file, which is
included by the C source file.
`source_name` is the file name of the C source file, which is
needed by the fuzzer makefile.
`fuzzer_source_name` is the file name of the C source file, which
is needed by the fuzzer makefile.
This function returns a tuple of the C header and source files as
strings.
"""
date = time.ctime()
namespace = camel_to_snake_case(namespace)
include_guard = '{}_H'.format(namespace.upper())
if codec == 'oer':
structs, declarations, helpers, definitions = oer.generate(
compiled,
namespace)
elif codec == 'uper':
structs, declarations, helpers, definitions = uper.generate(
compiled,
namespace)
else:
raise Exception()
header = HEADER_FMT.format(version=__version__,
date=date,
include_guard=include_guard,
structs=structs,
declarations=declarations)
source = SOURCE_FMT.format(version=__version__,
date=date,
header=header_name,
helpers=helpers,
definitions=definitions)
fuzzer_source, fuzzer_makefile = _generate_fuzzer_source(
namespace,
compiled,
date,
header_name,
source_name,
fuzzer_source_name)
return header, source, fuzzer_source, fuzzer_makefile
asn1tools-0.169.0/asn1tools/source/c/oer.py 0000664 0000000 0000000 00000126073 15245442746 0020444 0 ustar 00root root 0000000 0000000 """Basic Octet Encoding Rules (OER) C source code codec generator.
"""
from operator import itemgetter
import bitstruct
import textwrap
from .utils import ENCODER_AND_DECODER_STRUCTS
from .utils import Generator
from .utils import camel_to_snake_case
from .utils import is_user_type
from .utils import indent_lines
from .utils import dedent_lines
from .utils import canonical
from .oer_functions import functions
from ...codecs import oer
def get_encoded_real_lengths(type_):
return [4] if type_.fmt == '>f' else [8]
def get_sequence_optionals(type_):
return [
member
for member in type_.root_members
if member.optional or member.default is not None
]
def get_sequence_extension_bit(type_):
return 1 if type_.additions is not None else 0
def get_sequence_present_mask_length(optionals, extension_bit):
return (len(optionals) + extension_bit + 7) // 8
def get_length_determinant_length(length):
if length < 128:
return 1
elif length < 256:
return 2
elif length < 65536:
return 3
elif length < 1677726:
return 4
else:
return 5
def add_encoded_lengths(lengths):
length = 0
for length_part in lengths:
if isinstance(length_part, int):
length += length_part
else:
length = None
break
return length
def encoded_lengths_as_string(lengths):
length = 0
length_strings = []
for length_part in lengths:
if isinstance(length_part, int):
length += length_part
else:
length_strings.append(length_part)
if length > 0 or len(length_strings) == 0:
length_strings.append(str(length) + 'u')
return ' + '.join(length_strings)
def get_sequence_additions_mask_length(additions):
return (len(additions) + 7) // 8
def format_null_inner():
return (
[
'(void)encoder_p;',
'(void)src_p;'
],
[
'(void)decoder_p;',
'(void)dst_p;'
]
)
class _Generator(Generator):
def __init__(self, namespace):
super(_Generator, self).__init__(namespace)
self.additional_helpers = {}
def format_real(self, type_):
if type_.fmt is None:
raise self.error('REAL not IEEE 754 binary32 or binary64.')
if type_.fmt == '>f':
return ['float']
else:
return ['double']
def get_enumerated_value_length(self, value):
if -128 <= value < 128:
return 1
elif -32768 <= value < 32768:
return 2
elif -8388608 <= value < 8388608:
return 3
elif -2147483648 <= value < 2147483648:
return 4
else:
raise self.error(
'{} does not fit in int32_t.'.format(value))
def get_enumerated_values(self, type_):
return sorted([(canonical(data), value)
for data, value in type_.data_to_value.items()],
key=itemgetter(1))
def get_choice_members(self, type_):
return type_.root_members
def format_default(self, type_):
if isinstance(type_, oer.Boolean):
return str(type_.default).lower()
elif isinstance(type_, oer.Enumerated):
return self.format_default_enumerated(type_)
else:
return str(type_.default)
def format_type(self, type_, checker):
if isinstance(type_, oer.Integer):
return self.format_integer(checker)
elif isinstance(type_, oer.Boolean):
return self.format_boolean()
elif isinstance(type_, oer.Real):
return self.format_real(type_)
elif isinstance(type_, oer.Null):
return []
elif is_user_type(type_):
return self.format_user_type(type_.type_name,
type_.module_name)
elif isinstance(type_, oer.OctetString):
return self.format_octet_string(checker)
elif isinstance(type_, oer.Sequence):
return self.format_sequence(type_, checker)
elif isinstance(type_, oer.Choice):
return self.format_choice(type_, checker)
elif isinstance(type_, oer.SequenceOf):
return self.format_sequence_of(type_, checker)
elif isinstance(type_, oer.Enumerated):
return self.format_enumerated(type_)
elif isinstance(type_, oer.BitString):
return self.format_bit_string(type_, checker)
else:
raise self.error(
"Unsupported type '{}'.".format(type_.type_name))
def get_encoded_type_lengths(self, type_, checker):
if isinstance(type_, oer.Integer):
return self.get_encoded_integer_lengths(checker)
elif isinstance(type_, oer.Boolean):
return [1]
elif isinstance(type_, oer.Real):
return get_encoded_real_lengths(type_)
elif isinstance(type_, oer.Null):
return [0]
elif isinstance(type_, oer.OctetString):
return self.get_encoded_octet_string_lengths(type_, checker)
elif isinstance(type_, oer.Sequence):
return self.get_encoded_sequence_lengths(type_, checker)
elif isinstance(type_, oer.Choice):
return self.get_encoded_choice_lengths(type_, checker)
elif isinstance(type_, oer.SequenceOf):
return self.get_encoded_sequence_of_lengths(type_, checker)
elif isinstance(type_, oer.Enumerated):
return self.get_encoded_enumerated_length(type_)
else:
raise self.error(
"Unsupported type '{}'.".format(type_.type_name))
def generate_type_declaration_process(self, type_, checker):
if isinstance(type_, oer.Integer):
lines = self.format_integer(checker)
lines[0] += ' value;'
elif isinstance(type_, oer.Boolean):
lines = self.format_boolean()
lines[0] += ' value;'
elif isinstance(type_, oer.Real):
lines = self.format_real(type_)
lines[0] += ' value;'
elif isinstance(type_, oer.Enumerated):
lines = self.format_enumerated(type_)
lines[0] += ' value;'
elif isinstance(type_, oer.Sequence):
lines = self.format_sequence(type_, checker)[1:-1]
lines = dedent_lines(lines)
elif isinstance(type_, oer.SequenceOf):
lines = self.format_sequence_of(type_, checker)[1:-1]
lines = dedent_lines(lines)
elif isinstance(type_, oer.Choice):
lines = self.format_choice(type_, checker)
lines = dedent_lines(lines[1:-1])
elif isinstance(type_, oer.OctetString):
lines = self.format_octet_string(checker)[1:-1]
lines = dedent_lines(lines)
elif isinstance(type_, oer.BitString):
lines = self.format_bit_string(type_, checker)
lines[0] += ' value;'
elif isinstance(type_, oer.Null):
lines = []
else:
raise self.error(
"Unsupported type '{}'.".format(type_.type_name))
return lines
def format_integer_inner(self, checker):
type_name = self.format_type_name(checker.minimum, checker.maximum)[:-2]
return (
[
'encoder_append_{}(encoder_p, src_p->{});'.format(
type_name,
self.location_inner())
],
[
'dst_p->{} = decoder_read_{}(decoder_p);'.format(
self.location_inner(),
type_name)
]
)
def format_bit_string_inner(self, checker):
max_value = 2**checker.minimum - 1
type_name = self.format_type_name(max_value, max_value)
type_length = self.value_length(max_value)
if type_length <= 4:
encode_lines = [
'encoder_append_uint(encoder_p, (uint32_t)src_p->{}, {});'.format(
self.location_inner(),
type_length)
]
decode_lines = [
'dst_p->{} = ({})decoder_read_uint(decoder_p, {});'.format(
self.location_inner(),
type_name,
type_length)
]
else:
encode_lines = [
'encoder_append_long_uint(encoder_p, (uint64_t)src_p->{}, {});'.format(
self.location_inner(),
type_length)
]
decode_lines = [
'dst_p->{} = ({})decoder_read_long_uint(decoder_p, {});'.format(
self.location_inner(),
type_name,
type_length)
]
if type_length == 3:
decode_lines += [
'dst_p->{} &= 0x00ffffffu;'.format(
self.location_inner())
]
return encode_lines, decode_lines
def get_encoded_integer_lengths(self, checker):
return [self.type_length(checker.minimum, checker.maximum) // 8]
def format_boolean_inner(self):
return (
[
'encoder_append_bool(encoder_p, src_p->{});'.format(
self.location_inner())
],
[
'dst_p->{} = decoder_read_bool(decoder_p);'.format(
self.location_inner())
]
)
def format_real_inner(self, type_):
if type_.fmt == '>f':
c_type = 'float'
else:
c_type = 'double'
return (
[
'encoder_append_{}(encoder_p, src_p->{});'.format(
c_type,
self.location_inner())
],
[
'dst_p->{} = decoder_read_{}(decoder_p);'.format(
self.location_inner(),
c_type)
]
)
def format_sequence_inner(self, type_, checker):
encode_lines = []
decode_lines = []
optionals = get_sequence_optionals(type_)
extension_bit = get_sequence_extension_bit(type_)
present_mask_length = get_sequence_present_mask_length(optionals,
extension_bit)
default_condition_by_member_name = {}
if present_mask_length > 0:
fmt = 'uint8_t {{}}[{}];'.format(present_mask_length)
unique_present_mask = self.add_unique_variable(fmt, 'present_mask')
start_set_byte = 0
if extension_bit == 1 and len(type_.additions) > 0:
if_line = 'if({}) {{'.format(self.get_addition_present_condition(type_))
encode_lines.extend(textwrap.wrap(if_line, 100,
subsequent_indent=' ' * len('if(')))
encode_lines.append(' {}[0] = 0x80;'.format(unique_present_mask))
encode_lines.append('}')
encode_lines.append('else {')
encode_lines.append(' {}[0] = 0x0;'.format(unique_present_mask))
encode_lines.append('}')
start_set_byte = 1
for i in range(start_set_byte, present_mask_length):
encode_lines.append('{}[{}] = 0;'.format(unique_present_mask, i))
encode_lines.append('')
decode_lines += [
'decoder_read_bytes(decoder_p,',
' &{}[0],'.format(unique_present_mask),
' sizeof({}));'.format(unique_present_mask),
''
]
for i, member in enumerate(optionals, start=extension_bit):
byte, bit = divmod(i, 8)
mask = '0x{:02x}'.format(1 << (7 - bit))
present_mask = '{}[{}]'.format(unique_present_mask,
byte)
default_condition = '({0} & {1}u) == {1}u'.format(present_mask, mask)
default_condition_by_member_name[member.name] = default_condition
if member.optional:
encode_lines += [
'if (src_p->{}is_{}_present) {{'.format(
self.location_inner('', '.'),
canonical(member.name)),
' {} |= {}u;'.format(present_mask, mask),
'}',
''
]
decode_lines.append(
'dst_p->{0}is_{1}_present = (({2} & {3}u) == {3}u);'.format(
self.location_inner('', '.'),
canonical(member.name),
present_mask,
mask))
else:
inner = ' {} |= {}u;'.format(present_mask, mask)
if self.is_buffer_type(member):
default_variable = canonical(member.name) + '_default'
encode_lines += [
'if ((memcmp(src_p->{}{}.buf, {}, sizeof({})) != 0) ||'.format(
self.location_inner('', '.'),
canonical(member.name),
default_variable,
default_variable,
self.format_default(member)),
' (src_p->{}{}.length != sizeof({}))) {{'.format(
self.location_inner('', '.'),
canonical(member.name),
default_variable),
inner,
'}',
''
]
else:
encode_lines += [
'if (src_p->{}{}{} != {}) {{'.format(
self.location_inner('', '.'),
canonical(member.name),
'.value' if self.is_complex_user_type(member) else '',
self.format_default(member)),
inner,
'}',
''
]
encode_lines += [
'encoder_append_bytes(encoder_p,',
' &{}[0],'.format(unique_present_mask),
' sizeof({}));'.format(unique_present_mask),
''
]
decode_lines.append('')
for member in type_.root_members:
(member_encode_lines,
member_decode_lines) = self.format_sequence_inner_member(
member,
checker,
default_condition_by_member_name)
encode_lines += member_encode_lines
decode_lines += member_decode_lines
if type_.additions is not None and len(type_.additions) > 0:
additions_encode_lines, additions_decode_lines = (
self.format_sequence_additions(type_, checker))
addition_condition = 'if(({}[0] & 0x80u) == 0x80u) {{'.format(
unique_present_mask)
encode_lines += [
'',
addition_condition
] + indent_lines(additions_encode_lines) + [
'}'
]
decode_lines += [
'',
addition_condition
] + indent_lines(additions_decode_lines) + [
'}',
'else {'
] + [
' dst_p->{}is_{}_addition_present = false;'.format(
self.location_inner('', '.'), addition.name)
for addition in type_.additions] + [
'}'
]
return encode_lines, decode_lines
def format_sequence_additions(self, type_, checker):
encode_lines = ['']
decode_lines = ['']
addition_mask_length = get_sequence_additions_mask_length(type_.additions)
addition_mask_unused_bits = (addition_mask_length * 8) - len(type_.additions)
encode_lines.append('encoder_append_length_determinant(encoder_p, {});'.format(
addition_mask_length + 1))
unique_addition_length = self.add_unique_decode_variable(
'uint32_t {};', 'addition_length')
decode_lines += [
'{} = decoder_read_length_determinant(decoder_p);'.format(
unique_addition_length),
'',
'if({} <= 1u) {{'.format(unique_addition_length),
' decoder_abort(decoder_p, EBADLENGTH);',
'',
' return;',
'}',
'{} -= 1u;'.format(unique_addition_length)]
encode_lines.append('encoder_append_uint8(encoder_p, {});'.format(
addition_mask_unused_bits))
unique_addition_unused_bits = self.add_unique_decode_variable(
'uint8_t {};', 'addition_unused_bits')
unique_addition_bits = self.add_unique_decode_variable(
'uint32_t {};', 'addition_bits')
decode_lines += [
'{} = decoder_read_uint8(decoder_p);'.format(unique_addition_unused_bits),
'',
'if ({} > 7u) {{'.format(unique_addition_unused_bits),
' decoder_abort(decoder_p, EBADLENGTH);',
'',
' return;',
'}',
'{} = (({} * 8u) - {});'.format(unique_addition_bits, unique_addition_length,
unique_addition_unused_bits)]
fmt = 'uint8_t {{}}[{}];'.format(addition_mask_length)
unique_addition_mask = self.add_unique_variable(
fmt, 'addition_mask')
for i in range(addition_mask_length):
encode_lines.append('{}[{}] = 0;'.format(unique_addition_mask, i))
for i, addition in enumerate(type_.additions):
byte, bit = divmod(i, 8)
mask = '0x{:02x}'.format(1 << (7 - bit))
addition_mask = '{}[{}]'.format(unique_addition_mask,
byte)
encode_lines += [
'',
'if (src_p->{}is_{}_addition_present) {{'.format(
self.location_inner('', '.'), addition.name),
' {} |= {}u;'.format(addition_mask, mask),
'}'
]
encode_lines += [
'encoder_append_bytes(encoder_p,',
' &{}[0],'.format(unique_addition_mask),
' sizeof({}));'.format(unique_addition_mask)]
unique_i = self.add_unique_decode_variable('uint32_t {};', 'i')
unique_tmp_addition_mask = self.add_unique_decode_variable('uint8_t {};',
'tmp_addition_mask')
unique_unknown_addition_bits = self.add_unique_decode_variable(
'uint32_t {};', 'unknown_addition_bits')
unique_mask = self.add_unique_decode_variable('uint8_t {};', 'mask')
decode_lines += [
'decoder_read_bytes(decoder_p,',
' {mask},'.format(mask=unique_addition_mask),
' ({read} < {defined}u) ? {read} : {defined}u);'.format(
read=unique_addition_length, defined=addition_mask_length),
'',
'{} = {}[{}];'.format(unique_tmp_addition_mask, unique_addition_mask,
addition_mask_length - 1),
'{} = 0x{:02x};'.format(unique_mask, 0x80 >> (len(type_.additions) % 8)),
'{} = 0;'.format(unique_unknown_addition_bits),
'',
'for (i = {}; i < {}; i++) {{'.format(len(type_.additions),
unique_addition_bits),
'',
' if ({} == 0u) {{'.format(unique_mask),
' decoder_read_bytes(decoder_p, &{}, 1);'.format(
unique_tmp_addition_mask),
'',
' if (decoder_get_result(decoder_p) < 0) {',
'',
' return;',
' }',
' {} = 0x80;'.format(unique_mask),
' }',
'',
' if( ({tmp_addition} & {mask}) == {mask}) {{'.format(
tmp_addition=unique_tmp_addition_mask, mask=unique_mask),
' {} += 1u;'.format(unique_unknown_addition_bits),
' };',
' {} >>= 1;'.format(unique_mask),
'}'
]
for i, addition in enumerate(type_.additions):
byte, bit = divmod(i, 8)
mask = '0x{:02x}'.format(1 << (7 - bit))
(addition_encode_lines,
addition_decode_lines) = self.format_sequence_inner_member(
addition,
checker,
None,
skip_when_not_present=False)
member_checker = self.get_member_checker(checker, addition.name)
encoded_lengths = self.get_encoded_type_lengths(addition, member_checker)
encoder_line = 'encoder_append_length_determinant(encoder_p, {});'.format(
encoded_lengths_as_string(encoded_lengths))
wrapped_encoder_lines = textwrap.wrap(encoder_line, 100,
subsequent_indent=' ' * 4)
encode_lines += [
'',
'if (src_p->{}is_{}_addition_present) {{'
.format(self.location_inner('', '.'), addition.name)
] + indent_lines(wrapped_encoder_lines + addition_encode_lines) + [
'}'
]
decode_lines += [
'dst_p->{location}is_{name}_addition_present = '
'(({addition_bits} > {current_bit}u) && '
'(({addition_mask}[{index}] & {mask}u) == {mask}u));'.format(
location=self.location_inner('', '.'),
name=addition.name,
addition_bits=unique_addition_bits,
current_bit=i,
addition_mask=unique_addition_mask,
index=byte,
mask=mask),
'',
'if (dst_p->{location}is_{name}_addition_present) {{'.format(
location=self.location_inner('', '.'),
name=addition.name),
' (void)decoder_read_length_determinant(decoder_p);'
] + indent_lines(addition_decode_lines) + [
'}',
'']
unique_tmp_length = self.add_unique_decode_variable('uint32_t {};', 'tmp_length')
decode_lines += [
'for ({i} = 0; {i} < {unique_unknown_addition_bits}; {i}++) {{'.format(
i=unique_i,
first_bit=len(type_.additions),
unique_unknown_addition_bits=unique_unknown_addition_bits),
' {} = decoder_read_length_determinant(decoder_p);'.format(
unique_tmp_length),
'',
' if (decoder_free(decoder_p, {}) < 0) {{'.format(unique_tmp_length),
'',
' return;',
' }',
'}']
return encode_lines, decode_lines
def get_encoded_sequence_lengths(self, type_, checker):
lengths = []
optionals = get_sequence_optionals(type_)
extension_bit = get_sequence_extension_bit(type_)
lengths.append(get_sequence_present_mask_length(optionals,
extension_bit))
for member in type_.root_members:
member_checker = self.get_member_checker(checker, member.name)
lengths.extend(self.get_encoded_type_lengths(member, member_checker))
if type_.additions is not None and len(type_.additions) > 0:
additions_mask_length = (
get_sequence_additions_mask_length(type_.additions))
lengths.append(get_length_determinant_length(additions_mask_length))
lengths.append(1)
lengths.append(additions_mask_length)
for addition in type_.additions:
member_checker = self.get_member_checker(checker, addition.name)
additions_lengths = self.get_encoded_type_lengths(addition,
member_checker)
addition_length = add_encoded_lengths(additions_lengths)
if addition_length is not None:
lengths.append(get_length_determinant_length(addition_length))
else:
lengths.append('length_determinant_length({})'.format(
encoded_lengths_as_string(lengths)))
lengths.extend(additions_lengths)
return lengths
def format_octet_string_inner(self, checker):
location = self.location_inner('', '.')
if checker.minimum == checker.maximum:
encode_lines = [
'encoder_append_bytes(encoder_p,',
' &src_p->{}buf[0],'.format(location),
' {});'.format(checker.maximum)
]
decode_lines = [
'decoder_read_bytes(decoder_p,',
' &dst_p->{}buf[0],'.format(location),
' {});'.format(checker.maximum)
]
elif checker.maximum < 128:
encode_lines = [
'encoder_append_uint8(encoder_p, src_p->{}length);'.format(
location),
'encoder_append_bytes(encoder_p,',
' &src_p->{}buf[0],'.format(location),
' src_p->{}length);'.format(location)
]
decode_lines = [
'dst_p->{}length = decoder_read_uint8(decoder_p);'.format(
location),
'',
'if (dst_p->{}length > {}u) {{'.format(location, checker.maximum),
' decoder_abort(decoder_p, EBADLENGTH);',
'',
' return;',
'}',
'',
'decoder_read_bytes(decoder_p,',
' &dst_p->{}buf[0],'.format(location),
' dst_p->{}length);'.format(location)
]
else:
encode_lines = [
'encoder_append_length_determinant(encoder_p, src_p->{}length);'.format(
location),
'encoder_append_bytes(encoder_p,',
' &src_p->{}buf[0],'.format(location),
' src_p->{}length);'.format(location)
]
decode_lines = [
'dst_p->{}length = decoder_read_length_determinant(decoder_p);'.format(
location),
'',
'if (dst_p->{}length > {}u) {{'.format(location, checker.maximum),
' decoder_abort(decoder_p, EBADLENGTH);',
'',
' return;',
'}',
'',
'decoder_read_bytes(decoder_p,',
' &dst_p->{}buf[0],'.format(location),
' dst_p->{}length);'.format(location)
]
return encode_lines, decode_lines
def get_encoded_octet_string_lengths(self, type_, checker):
with self.members_backtrace_push(type_.name):
if checker.minimum == checker.maximum:
return [checker.maximum]
else:
location = self.location_inner('', '.')
src_length = 'src_p->{}length'.format(location)
return ['length_determinant_length({})'.format(src_length),
src_length]
def format_user_type_inner(self, type_name, module_name):
prefix = self.get_user_type_prefix(type_name, module_name)
encode_lines = [
'{}_encode_inner(encoder_p, &src_p->{});'.format(
prefix,
self.location_inner())
]
decode_lines = [
'{}_decode_inner(decoder_p, &dst_p->{});'.format(
prefix,
self.location_inner())
]
return encode_lines, decode_lines
def format_choice_inner(self, type_, checker):
encode_lines = []
decode_lines = []
unique_tag = self.add_unique_decode_variable('uint32_t {};', 'tag')
choice = '{}choice'.format(self.location_inner('', '.'))
for member in type_.root_members:
member_checker = self.get_member_checker(checker,
member.name)
with self.asn1_members_backtrace_push(canonical(member.name)):
with self.c_members_backtrace_push('value'):
with self.c_members_backtrace_push(canonical(member.name)):
choice_encode_lines, choice_decode_lines = self.format_type_inner(
member,
member_checker)
tag_length = len(member.tag)
if tag_length > 4:
raise self.error(
'CHOICE tags of more than four bytes are not yet supported.')
tag = bitstruct.unpack('u{}'.format(8 * tag_length),
member.tag)[0]
tag = '0x{{:0{}x}}'.format(2 * tag_length).format(tag)
choice_encode_lines = [
'encoder_append_uint(encoder_p, {}, {});'.format(
tag,
tag_length)
] + choice_encode_lines + [
'break;'
]
encode_lines += [
'case {}_choice_{}_e:'.format(self.location, canonical(member.name))
] + indent_lines(choice_encode_lines) + [
''
]
choice_decode_lines = [
'dst_p->{} = {}_choice_{}_e;'.format(choice,
self.location,
canonical(member.name))
] + choice_decode_lines + [
'break;'
]
decode_lines += [
'case {}:'.format(tag)
] + indent_lines(choice_decode_lines) + [
''
]
encode_lines = [
'',
'switch (src_p->{}) {{'.format(choice),
''
] + encode_lines + [
'default:',
' encoder_abort(encoder_p, EBADCHOICE);',
' break;',
'}',
''
]
decode_lines = [
'{} = decoder_read_tag(decoder_p);'.format(unique_tag),
'',
'switch ({}) {{'.format(unique_tag),
''
] + decode_lines + [
'default:',
' decoder_abort(decoder_p, EBADCHOICE);',
' break;',
'}',
''
]
return encode_lines, decode_lines
def get_encoded_choice_lengths(self, type_, checker):
function_name = 'get_choice_{}_length'.format(camel_to_snake_case(type_.name))
if function_name not in self.additional_helpers:
with self.members_backtrace_push(type_.name):
choice = '{}choice'.format(self.location_inner('', '.'))
choice_length_lines = []
for member in type_.root_members:
member_checker = self.get_member_checker(checker,
member.name)
with self.asn1_members_backtrace_push(canonical(member.name)):
with self.c_members_backtrace_push('value'):
with self.c_members_backtrace_push(canonical(member.name)):
choice_type_lengths = self.get_encoded_type_lengths(
member,
member_checker)
choice_type_lengths.append(len(member.tag))
length_line = 'length = {};'.format(
encoded_lengths_as_string(choice_type_lengths))
wrapped_length_lines = textwrap.wrap(length_line, 100,
subsequent_indent=' ' * 4)
choice_length_lines += [
'case {}_choice_{}_e:'.format(self.location, canonical(member.name))
] + indent_lines(wrapped_length_lines) + [
' break;',
'']
length_lines = [
'uint32_t length;',
'',
'switch (src_p->{}) {{'.format(choice),
''
] + choice_length_lines + [
'default:',
' length = 0;'
' break;',
'}',
'return length;']
length_lines = [
'static uint32_t {}(const struct {}_t *src_p) {{'.format(
function_name, self.location)
] + indent_lines(length_lines) + [
'}']
self.additional_helpers[function_name] = length_lines
return ['{}(src_p)'.format(function_name)]
def format_enumerated_inner(self, type_):
encode_lines = []
decode_lines = []
max_value = max(type_.value_to_data)
min_value = min(type_.value_to_data)
type_name = '{}_e'.format(self.location)
type_length = max(self.get_enumerated_value_length(min_value),
self.get_enumerated_value_length(max_value))
unique_enum_length = self.add_unique_variable('uint8_t {};',
'enum_length')
encode_lines += [
'{} = enumerated_value_length(src_p->{});'.format(
unique_enum_length, self.location_inner()),
'',
'if ({} != 0u) {{'.format(unique_enum_length),
' encoder_append_uint8(encoder_p, 0x80u | {});'.format(
unique_enum_length),
' encoder_append_int(encoder_p, (int32_t)src_p->{}, {});'.format(
self.location_inner(), unique_enum_length),
'}',
'else {',
' encoder_append_uint8(encoder_p, (uint8_t)src_p->{});'.format(
self.location_inner()),
'}']
decode_lines += [
'{} = decoder_read_uint8(decoder_p);'.format(unique_enum_length),
'',
'if (({} & 0x80u) == 0x80u) {{'.format(unique_enum_length),
' {} &= 0x7fu;'.format(unique_enum_length),
'',
' if (({length} > {type_length}u) || ({length} == 0u)) {{'.format(
type_length=type_length, length=unique_enum_length),
' decoder_abort(decoder_p, EBADLENGTH);',
'',
' return;',
' }',
' dst_p->{} = (enum {})decoder_read_int(decoder_p, {});'.format(
self.location_inner(), type_name, unique_enum_length),
'}',
'else {',
' dst_p->{} = (enum {}){};'.format(self.location_inner(), type_name,
unique_enum_length),
'}']
return encode_lines, decode_lines
def get_encoded_enumerated_length(self, type_):
with self.members_backtrace_push(type_.name):
return ['(uint32_t)enumerated_value_length((int32_t)src_p->{})'.format(
self.location_inner()), 1]
def format_sequence_of_inner(self, type_, checker):
unique_number_of_length_bytes = self.add_unique_variable(
'uint8_t {};',
'number_of_length_bytes')
unique_i = self.add_unique_variable(
'{} {{}};'.format(self.format_type_name(0, checker.maximum)),
'i')
if checker.minimum == checker.maximum:
unique_length = self.add_unique_decode_variable('uint8_t {};',
'length')
with self.c_members_backtrace_push('elements[{}]'.format(unique_i)):
encode_lines, decode_lines = self.format_type_inner(
type_.element_type,
checker.element_type)
location = self.location_inner('', '.')
if checker.minimum == checker.maximum:
encode_lines = [
'{} = minimum_uint_length({});'.format(
unique_number_of_length_bytes,
checker.maximum),
'encoder_append_uint8(encoder_p, {});'.format(
unique_number_of_length_bytes),
'encoder_append_uint(encoder_p,',
' {},'.format(checker.maximum),
' {});'.format(unique_number_of_length_bytes),
'',
'for ({ui} = 0; {ui} < {maximum}u; {ui}++) {{'.format(
ui=unique_i,
maximum=checker.maximum),
] + indent_lines(encode_lines)
decode_lines = [
'{} = decoder_read_uint8(decoder_p);'.format(
unique_number_of_length_bytes),
'{} = decoder_read_uint8(decoder_p);'.format(unique_length),
'',
'if (({} != 1u) || ({} > {}u)) {{'.format(unique_number_of_length_bytes,
unique_length,
checker.maximum),
' decoder_abort(decoder_p, EBADLENGTH);',
'',
' return;',
'}',
'',
'for ({ui} = 0; {ui} < {maximum}u; {ui}++) {{'.format(
ui=unique_i,
maximum=checker.maximum),
] + indent_lines(decode_lines)
else:
if checker.maximum < 256:
cast = '(uint8_t)'
else:
cast = ''
encode_lines = [
'{} = minimum_uint_length(src_p->{}length);'.format(
unique_number_of_length_bytes,
location),
'encoder_append_uint8(encoder_p, {});'.format(
unique_number_of_length_bytes),
'encoder_append_uint(encoder_p,',
' src_p->{}length,'.format(location),
' {});'.format(unique_number_of_length_bytes),
'',
'for ({ui} = 0; {ui} < src_p->{loc}length; {ui}++) {{'.format(
ui=unique_i,
loc=location),
] + indent_lines(encode_lines)
decode_lines = [
'{} = decoder_read_uint8(decoder_p);'.format(
unique_number_of_length_bytes),
'dst_p->{}length = {}decoder_read_uint('.format(location, cast),
' decoder_p,',
' {});'.format(unique_number_of_length_bytes),
'',
'if (dst_p->{}length > {}u) {{'.format(location, checker.maximum),
' decoder_abort(decoder_p, EBADLENGTH);',
'',
' return;',
'}',
'',
'for ({ui} = 0; {ui} < dst_p->{loc}length; {ui}++) {{'.format(
loc=location,
ui=unique_i),
] + indent_lines(decode_lines)
encode_lines += ['}', '']
decode_lines += ['}', '']
return encode_lines, decode_lines
def get_encoded_sequence_of_lengths(self, type_, checker):
inner_lengths = self.get_encoded_type_lengths(type_.element_type,
checker.element_type)
inner_length = encoded_lengths_as_string(inner_lengths)
with self.c_members_backtrace_push(type_.name):
return [1,
'(uint32_t)minimum_uint_length(src_p->{loc}length)'.format(
loc=self.location_inner('', '.')),
'(uint32_t)(src_p->{loc}length * ({inner_length}))'.format(
loc=self.location_inner('', '.'), inner_length=inner_length)]
def format_type_inner(self, type_, checker):
if isinstance(type_, oer.Integer):
return self.format_integer_inner(checker)
elif isinstance(type_, oer.Real):
return self.format_real_inner(type_)
elif isinstance(type_, oer.Null):
return [], []
elif isinstance(type_, oer.Boolean):
return self.format_boolean_inner()
elif is_user_type(type_):
return self.format_user_type_inner(type_.type_name,
type_.module_name)
elif isinstance(type_, oer.OctetString):
return self.format_octet_string_inner(checker)
elif isinstance(type_, oer.Sequence):
return self.format_sequence_inner(type_, checker)
elif isinstance(type_, oer.Choice):
return self.format_choice_inner(type_, checker)
elif isinstance(type_, oer.SequenceOf):
return self.format_sequence_of_inner(type_, checker)
elif isinstance(type_, oer.Enumerated):
return self.format_enumerated_inner(type_)
elif isinstance(type_, oer.BitString):
return self.format_bit_string_inner(checker)
else:
raise self.error(str(type_))
def generate_definition_inner_process(self, type_, checker):
if isinstance(type_, oer.Integer):
return self.format_integer_inner(checker)
elif isinstance(type_, oer.Boolean):
return self.format_boolean_inner()
elif isinstance(type_, oer.Real):
return self.format_real_inner(type_)
elif isinstance(type_, oer.Sequence):
return self.format_sequence_inner(type_, checker)
elif isinstance(type_, oer.SequenceOf):
return self.format_sequence_of_inner(type_, checker)
elif isinstance(type_, oer.Choice):
return self.format_choice_inner(type_, checker)
elif isinstance(type_, oer.OctetString):
return self.format_octet_string_inner(checker)
elif isinstance(type_, oer.BitString):
return self.format_bit_string_inner(checker)
elif isinstance(type_, oer.Enumerated):
return self.format_enumerated_inner(type_)
elif isinstance(type_, oer.Null):
return format_null_inner()
else:
return [], []
def is_complex_user_type(self, type_):
return is_user_type(type_) and \
not isinstance(type_, (oer.Integer, oer.Boolean, oer.Real, oer.Null))
def is_buffer_type(self, type_):
return isinstance(type_, oer.OctetString)
def generate_helpers(self, definitions):
helpers = []
for pattern, definition in functions:
is_in_helpers = any([pattern in helper for helper in helpers])
if pattern in definitions or is_in_helpers:
helpers.insert(0, definition)
for additional_helpers in self.additional_helpers.values():
helpers.extend(additional_helpers + [''])
return [ENCODER_AND_DECODER_STRUCTS] + helpers + ['']
def generate(compiled, namespace):
return _Generator(namespace).generate(compiled)
asn1tools-0.169.0/asn1tools/source/c/oer_functions.py 0000664 0000000 0000000 00000037662 15245442746 0022541 0 ustar 00root root 0000000 0000000 """Functions required by the OER C code generator
"""
from .utils import ENCODER_ABORT
from .utils import DECODER_ABORT
ENUMERATED_VALUE_LENGTH = '''
static uint8_t enumerated_value_length(int32_t value)
{
uint8_t length;
if ((value >=0) && (value < 128)) {
length = 0;
} else if ((value >= -128) && (value < 128)) {
length = 1;
} else if ((value >= -32768) && (value < 32768)) {
length = 2;
} else if ((value >= -8388608) && (value < 8388608)) {
length = 3;
} else {
length = 4;
}
return length;
}\
'''
LENGTH_DETERMINANT_LENGTH = '''
static uint32_t length_determinant_length(uint32_t value)
{
uint32_t length;
if (value < 128u) {
length = 1;
} else if (value < 256u) {
length = 2;
} else if (value < 65536u) {
length = 3;
} else if (value < 16777216u) {
length = 4;
} else {
length = 5;
}
return (length);
}\
'''
MINIMUM_UINT_LENGTH = '''
static uint8_t minimum_uint_length(uint32_t value)
{
uint8_t length;
if (value < 256u) {
length = 1;
} else if (value < 65536u) {
length = 2;
} else if (value < 16777216u) {
length = 3;
} else {
length = 4;
}
return (length);
}\
'''
ENCODER_INIT = '''\
static void encoder_init(struct encoder_t *self_p,
uint8_t *buf_p,
size_t size)
{
self_p->buf_p = buf_p;
self_p->size = (ssize_t)size;
self_p->pos = 0;
}\
'''
ENCODER_GET_RESULT = '''
static ssize_t encoder_get_result(const struct encoder_t *self_p)
{
return (self_p->pos);
}\
'''
ENCODER_ALLOC = '''
static ssize_t encoder_alloc(struct encoder_t *self_p,
size_t size)
{
ssize_t pos;
if ((self_p->pos + (ssize_t)size) <= self_p->size) {
pos = self_p->pos;
self_p->pos += (ssize_t)size;
} else {
pos = -ENOMEM;
encoder_abort(self_p, ENOMEM);
}
return (pos);
}\
'''
ENCODER_APPEND_BYTES = '''
static void encoder_append_bytes(struct encoder_t *self_p,
const uint8_t *buf_p,
size_t size)
{
ssize_t pos;
pos = encoder_alloc(self_p, size);
if (pos < 0) {
return;
}
(void)memcpy(&self_p->buf_p[pos], buf_p, size);
}\
'''
ENCODER_APPEND_UINT8 = '''
static void encoder_append_uint8(struct encoder_t *self_p,
uint8_t value)
{
encoder_append_bytes(self_p, &value, sizeof(value));
}\
'''
ENCODER_APPEND_UINT16 = '''
static void encoder_append_uint16(struct encoder_t *self_p,
uint16_t value)
{
uint8_t buf[2];
buf[0] = (uint8_t)(value >> 8);
buf[1] = (uint8_t)value;
encoder_append_bytes(self_p, &buf[0], sizeof(buf));
}\
'''
ENCODER_APPEND_UINT32 = '''
static void encoder_append_uint32(struct encoder_t *self_p,
uint32_t value)
{
uint8_t buf[4];
buf[0] = (uint8_t)(value >> 24);
buf[1] = (uint8_t)(value >> 16);
buf[2] = (uint8_t)(value >> 8);
buf[3] = (uint8_t)value;
encoder_append_bytes(self_p, &buf[0], sizeof(buf));
}\
'''
ENCODER_APPEND_UINT64 = '''
static void encoder_append_uint64(struct encoder_t *self_p,
uint64_t value)
{
uint8_t buf[8];
buf[0] = (uint8_t)(value >> 56);
buf[1] = (uint8_t)(value >> 48);
buf[2] = (uint8_t)(value >> 40);
buf[3] = (uint8_t)(value >> 32);
buf[4] = (uint8_t)(value >> 24);
buf[5] = (uint8_t)(value >> 16);
buf[6] = (uint8_t)(value >> 8);
buf[7] = (uint8_t)value;
encoder_append_bytes(self_p, &buf[0], sizeof(buf));
}\
'''
ENCODER_APPEND_INT8 = '''
static void encoder_append_int8(struct encoder_t *self_p,
int8_t value)
{
encoder_append_uint8(self_p, (uint8_t)value);
}\
'''
ENCODER_APPEND_INT16 = '''
static void encoder_append_int16(struct encoder_t *self_p,
int16_t value)
{
encoder_append_uint16(self_p, (uint16_t)value);
}\
'''
ENCODER_APPEND_INT32 = '''
static void encoder_append_int32(struct encoder_t *self_p,
int32_t value)
{
encoder_append_uint32(self_p, (uint32_t)value);
}\
'''
ENCODER_APPEND_INT64 = '''
static void encoder_append_int64(struct encoder_t *self_p,
int64_t value)
{
encoder_append_uint64(self_p, (uint64_t)value);
}\
'''
ENCODER_APPEND_UINT = '''
static void encoder_append_uint(struct encoder_t *self_p,
uint32_t value,
uint8_t number_of_bytes)
{
switch (number_of_bytes) {
case 1:
encoder_append_uint8(self_p, (uint8_t)value);
break;
case 2:
encoder_append_uint16(self_p, (uint16_t)value);
break;
case 3:
encoder_append_uint8(self_p, (uint8_t)(value >> 16));
encoder_append_uint16(self_p, (uint16_t)value);
break;
default:
encoder_append_uint32(self_p, value);
break;
}
}\
'''
ENCODER_APPEND_LONG_UINT = '''
static void encoder_append_long_uint(struct encoder_t *self_p,
uint64_t value,
uint8_t number_of_bytes)
{
const uint8_t *value_p = (const uint8_t*)&value;
uint8_t buf[8];
for(uint32_t byte = 0; byte < number_of_bytes; byte++) {
buf[number_of_bytes - byte - 1] = *value_p++;
}
encoder_append_bytes(self_p, buf, number_of_bytes);
}\
'''
ENCODER_APPEND_INT = '''
static void encoder_append_int(struct encoder_t *self_p,
int32_t value,
uint8_t number_of_bytes)
{
switch (number_of_bytes) {
case 1:
encoder_append_int8(self_p, (int8_t)value);
break;
case 2:
encoder_append_int16(self_p, (int16_t)value);
break;
case 3:
encoder_append_uint8(self_p, (uint8_t)((uint32_t)value >> 16));
encoder_append_int16(self_p, (int16_t)value);
break;
default:
encoder_append_int32(self_p, value);
break;
}
}\
'''
ENCODER_APPEND_FLOAT = '''
static void encoder_append_float(struct encoder_t *self_p,
float value)
{
uint32_t i32;
(void)memcpy(&i32, &value, sizeof(i32));
encoder_append_uint32(self_p, i32);
}\
'''
ENCODER_APPEND_DOUBLE = '''
static void encoder_append_double(struct encoder_t *self_p,
double value)
{
uint64_t i64;
(void)memcpy(&i64, &value, sizeof(i64));
encoder_append_uint64(self_p, i64);
}\
'''
ENCODER_APPEND_BOOL = '''
static void encoder_append_bool(struct encoder_t *self_p, bool value)
{
encoder_append_uint8(self_p, value ? 255u : 0u);
}\
'''
ENCODER_APPEND_LENGTH_DETERMINANT = '''
static void encoder_append_length_determinant(struct encoder_t *self_p,
uint32_t length)
{
if (length < 128u) {
encoder_append_int8(self_p, (int8_t)length);
} else if (length < 256u) {
encoder_append_uint8(self_p, 0x81u);
encoder_append_uint8(self_p, (uint8_t)length);
} else if (length < 65536u) {
encoder_append_uint8(self_p, 0x82u);
encoder_append_uint16(self_p, (uint16_t)length);
} else if (length < 16777216u) {
encoder_append_uint32(self_p, length | (0x83u << 24u));
} else {
encoder_append_uint8(self_p, 0x84u);
encoder_append_uint32(self_p, length);
}
}\
'''
DECODER_INIT = '''
static void decoder_init(struct decoder_t *self_p,
const uint8_t *buf_p,
size_t size)
{
self_p->buf_p = buf_p;
self_p->size = (ssize_t)size;
self_p->pos = 0;
}\
'''
DECODER_GET_RESULT = '''
static ssize_t decoder_get_result(const struct decoder_t *self_p)
{
return (self_p->pos);
}\
'''
DECODER_FREE = '''
static ssize_t decoder_free(struct decoder_t *self_p,
size_t size)
{
ssize_t pos;
if ((self_p->pos + (ssize_t)size) <= self_p->size) {
pos = self_p->pos;
self_p->pos += (ssize_t)size;
} else {
pos = -EOUTOFDATA;
decoder_abort(self_p, EOUTOFDATA);
}
return (pos);
}\
'''
DECODER_READ_BYTES = '''
static void decoder_read_bytes(struct decoder_t *self_p,
uint8_t *buf_p,
size_t size)
{
ssize_t pos;
pos = decoder_free(self_p, size);
if (pos >= 0) {
(void)memcpy(buf_p, &self_p->buf_p[pos], size);
} else {
(void)memset(buf_p, 0, size);
}
}\
'''
DECODER_READ_UINT8 = '''
static uint8_t decoder_read_uint8(struct decoder_t *self_p)
{
uint8_t value;
decoder_read_bytes(self_p, &value, sizeof(value));
return (value);
}\
'''
DECODER_READ_UINT16 = '''
static uint16_t decoder_read_uint16(struct decoder_t *self_p)
{
uint8_t buf[2];
decoder_read_bytes(self_p, &buf[0], sizeof(buf));
return (uint16_t)(((uint16_t)buf[0] << 8) | (uint16_t)buf[1]);
}\
'''
DECODER_READ_UINT32 = '''
static uint32_t decoder_read_uint32(struct decoder_t *self_p)
{
uint8_t buf[4];
decoder_read_bytes(self_p, &buf[0], sizeof(buf));
return (((uint32_t)buf[0] << 24)
| ((uint32_t)buf[1] << 16)
| ((uint32_t)buf[2] << 8)
| (uint32_t)buf[3]);
}\
'''
DECODER_READ_UINT64 = '''
static uint64_t decoder_read_uint64(struct decoder_t *self_p)
{
uint8_t buf[8];
decoder_read_bytes(self_p, &buf[0], sizeof(buf));
return (((uint64_t)buf[0] << 56)
| ((uint64_t)buf[1] << 48)
| ((uint64_t)buf[2] << 40)
| ((uint64_t)buf[3] << 32)
| ((uint64_t)buf[4] << 24)
| ((uint64_t)buf[5] << 16)
| ((uint64_t)buf[6] << 8)
| (uint64_t)buf[7]);
}\
'''
DECODER_READ_INT8 = '''
static int8_t decoder_read_int8(struct decoder_t *self_p)
{
return ((int8_t)decoder_read_uint8(self_p));
}\
'''
DECODER_READ_INT16 = '''
static int16_t decoder_read_int16(struct decoder_t *self_p)
{
return ((int16_t)decoder_read_uint16(self_p));
}\
'''
DECODER_READ_INT32 = '''
static int32_t decoder_read_int32(struct decoder_t *self_p)
{
return ((int32_t)decoder_read_uint32(self_p));
}\
'''
DECODER_READ_INT64 = '''
static int64_t decoder_read_int64(struct decoder_t *self_p)
{
return ((int64_t)decoder_read_uint64(self_p));
}\
'''
DECODER_READ_UINT = '''
static uint32_t decoder_read_uint(struct decoder_t *self_p,
uint8_t number_of_bytes)
{
uint32_t value;
switch (number_of_bytes) {
case 1:
value = decoder_read_uint8(self_p);
break;
case 2:
value = decoder_read_uint16(self_p);
break;
case 3:
value = ((uint32_t)decoder_read_uint8(self_p) << 16u);
value |= decoder_read_uint16(self_p);
break;
case 4:
value = decoder_read_uint32(self_p);
break;
default:
value = 0xffffffffu;
break;
}
return (value);
}\
'''
DECODER_READ_LONG_UINT = '''
static uint64_t decoder_read_long_uint(struct decoder_t *self_p,
uint8_t number_of_bytes)
{
uint64_t value = 0;
for(uint8_t byte = 0; byte < number_of_bytes; byte++) {
value = decoder_read_uint8(self_p) | (value << 8);
}
return (value);
}\
'''
DECODER_READ_INT = '''
static int32_t decoder_read_int(struct decoder_t *self_p,
uint8_t number_of_bytes)
{
int32_t value;
uint32_t tmp;
switch (number_of_bytes) {
case 1:
value = decoder_read_int8(self_p);
break;
case 2:
value = decoder_read_int16(self_p);
break;
case 3:
tmp = ((uint32_t)decoder_read_uint8(self_p) << 16u);
tmp |= decoder_read_uint16(self_p);
if((tmp & 0x800000u) == 0x800000u) {
tmp += 0xff000000u;
}
value = (int32_t)tmp;
break;
case 4:
value = decoder_read_int32(self_p);
break;
default:
value = 2147483647;
break;
}
return (value);
}\
'''
DECODER_READ_FLOAT = '''
static float decoder_read_float(struct decoder_t *self_p)
{
float value;
uint32_t i32;
i32 = decoder_read_uint32(self_p);
(void)memcpy(&value, &i32, sizeof(value));
return (value);
}\
'''
DECODER_READ_DOUBLE = '''
static double decoder_read_double(struct decoder_t *self_p)
{
double value;
uint64_t i64;
i64 = decoder_read_uint64(self_p);
(void)memcpy(&value, &i64, sizeof(value));
return (value);
}\
'''
DECODER_READ_BOOL = '''
static bool decoder_read_bool(struct decoder_t *self_p)
{
return (decoder_read_uint8(self_p) != 0u);
}\
'''
DECODER_READ_LENGTH_DETERMINANT = '''
static uint32_t decoder_read_length_determinant(struct decoder_t *self_p)
{
uint32_t length;
length = decoder_read_uint8(self_p);
if ((length & 0x80u) != 0u) {
switch (length & 0x7fu) {
case 1:
length = decoder_read_uint8(self_p);
break;
case 2:
length = decoder_read_uint16(self_p);
break;
case 3:
length = (((uint32_t)decoder_read_uint8(self_p) << 16)
| decoder_read_uint16(self_p));
break;
case 4:
length = decoder_read_uint32(self_p);
break;
default:
length = 0xffffffffu;
break;
}
}
return (length);
}\
'''
DECODER_READ_TAG = '''
static uint32_t decoder_read_tag(struct decoder_t *self_p)
{
uint32_t tag;
tag = decoder_read_uint8(self_p);
if ((tag & 0x3fu) == 0x3fu) {
do {
tag <<= 8;
tag |= (uint32_t)decoder_read_uint8(self_p);
} while ((tag & 0x80u) == 0x80u);
}
return (tag);
}\
'''
functions = [
('decoder_read_tag(', DECODER_READ_TAG),
('decoder_read_length_determinant(', DECODER_READ_LENGTH_DETERMINANT),
('decoder_read_bool(', DECODER_READ_BOOL),
('decoder_read_double(', DECODER_READ_DOUBLE),
('decoder_read_float(', DECODER_READ_FLOAT),
('decoder_read_int(', DECODER_READ_INT),
('decoder_read_uint(', DECODER_READ_UINT),
('decoder_read_long_uint(', DECODER_READ_LONG_UINT),
('decoder_read_int64(', DECODER_READ_INT64),
('decoder_read_int32(', DECODER_READ_INT32),
('decoder_read_int16(', DECODER_READ_INT16),
('decoder_read_int8(', DECODER_READ_INT8),
('decoder_read_uint64(', DECODER_READ_UINT64),
('decoder_read_uint32(', DECODER_READ_UINT32),
('decoder_read_uint16(', DECODER_READ_UINT16),
('decoder_read_uint8(', DECODER_READ_UINT8),
('decoder_read_bytes(', DECODER_READ_BYTES),
('decoder_free(', DECODER_FREE),
('decoder_abort(', DECODER_ABORT),
('decoder_get_result(', DECODER_GET_RESULT),
('decoder_init(', DECODER_INIT),
('encoder_append_length_determinant(', ENCODER_APPEND_LENGTH_DETERMINANT),
('encoder_append_bool(', ENCODER_APPEND_BOOL),
('encoder_append_double(', ENCODER_APPEND_DOUBLE),
('encoder_append_float(', ENCODER_APPEND_FLOAT),
('encoder_append_int(', ENCODER_APPEND_INT),
('encoder_append_uint(', ENCODER_APPEND_UINT),
('encoder_append_long_uint(', ENCODER_APPEND_LONG_UINT),
('encoder_append_int64(', ENCODER_APPEND_INT64),
('encoder_append_int32(', ENCODER_APPEND_INT32),
('encoder_append_int16(', ENCODER_APPEND_INT16),
('encoder_append_int8(', ENCODER_APPEND_INT8),
('encoder_append_uint64(', ENCODER_APPEND_UINT64),
('encoder_append_uint32(', ENCODER_APPEND_UINT32),
('encoder_append_uint16(', ENCODER_APPEND_UINT16),
('encoder_append_uint8(', ENCODER_APPEND_UINT8),
('encoder_append_bytes(', ENCODER_APPEND_BYTES),
('encoder_alloc(', ENCODER_ALLOC),
('encoder_abort(', ENCODER_ABORT),
('encoder_get_result(', ENCODER_GET_RESULT),
('encoder_init(', ENCODER_INIT),
('minimum_uint_length(', MINIMUM_UINT_LENGTH),
('length_determinant_length(', LENGTH_DETERMINANT_LENGTH),
('enumerated_value_length(', ENUMERATED_VALUE_LENGTH)
]
asn1tools-0.169.0/asn1tools/source/c/uper.py 0000664 0000000 0000000 00000061105 15245442746 0020624 0 ustar 00root root 0000000 0000000 """Unaligned Packed Encoding Rules (UPER) C source code codec generator.
"""
import textwrap
from .utils import ENCODER_AND_DECODER_STRUCTS
from .utils import Generator
from .utils import camel_to_snake_case
from .utils import is_user_type
from .utils import indent_lines
from .utils import dedent_lines
from .utils import canonical
from .uper_functions import functions
from ...codecs import uper
def does_bits_match_range(number_of_bits, minimum, maximum):
return 2 ** number_of_bits == (maximum - minimum + 1)
class _Generator(Generator):
def format_real(self):
return []
def get_enumerated_values(self, type_):
return sorted([(canonical(data), value)
for data, value in type_.root_data_to_value.items()])
def get_choice_members(self, type_):
return type_.root_index_to_member.values()
def format_default(self, type_):
if isinstance(type_, uper.Boolean):
return str(type_.default).lower()
elif isinstance(type_, uper.Enumerated):
return self.format_default_enumerated(type_)
else:
return str(type_.default)
def format_type(self, type_, checker):
if isinstance(type_, uper.Integer):
return self.format_integer(checker)
elif isinstance(type_, uper.Boolean):
return self.format_boolean()
elif isinstance(type_, uper.Real):
return self.format_real()
elif isinstance(type_, uper.Null):
return []
elif is_user_type(type_):
return self.format_user_type(type_.type_name,
type_.module_name)
elif isinstance(type_, uper.OctetString):
return self.format_octet_string(checker)
elif isinstance(type_, uper.Sequence):
return self.format_sequence(type_, checker)
elif isinstance(type_, uper.Choice):
return self.format_choice(type_, checker)
elif isinstance(type_, uper.SequenceOf):
return self.format_sequence_of(type_, checker)
elif isinstance(type_, uper.Enumerated):
return self.format_enumerated(type_)
elif isinstance(type_, uper.BitString):
return self.format_bit_string(type_, checker)
else:
raise self.error(
"Unsupported type '{}'.".format(type_.type_name))
def generate_type_declaration_process(self, type_, checker):
if isinstance(type_, uper.Integer):
lines = self.format_integer(checker)
lines[0] += ' value;'
elif isinstance(type_, uper.Boolean):
lines = self.format_boolean()
lines[0] += ' value;'
elif isinstance(type_, uper.Real):
lines = self.format_real()
elif isinstance(type_, uper.Enumerated):
lines = self.format_enumerated(type_)
lines[0] += ' value;'
elif isinstance(type_, uper.Sequence):
lines = self.format_sequence(type_, checker)[1:-1]
lines = dedent_lines(lines)
elif isinstance(type_, uper.SequenceOf):
lines = self.format_sequence_of(type_, checker)[1:-1]
lines = dedent_lines(lines)
elif isinstance(type_, uper.Choice):
lines = self.format_choice(type_, checker)
lines = dedent_lines(lines[1:-1])
elif isinstance(type_, uper.OctetString):
lines = self.format_octet_string(checker)[1:-1]
lines = dedent_lines(lines)
elif isinstance(type_, uper.BitString):
lines = self.format_bit_string(type_, checker)
lines[0] += ' value;'
elif isinstance(type_, uper.Null):
lines = []
else:
raise self.error(
"Unsupported type '{}'.".format(type_.type_name))
return lines
def generate_definition_inner_process(self, type_, checker):
if isinstance(type_, uper.Integer):
return self.format_integer_inner(type_, checker)
elif isinstance(type_, uper.Boolean):
return self.format_boolean_inner()
elif isinstance(type_, uper.Real):
return self.format_real_inner()
elif isinstance(type_, uper.Sequence):
return self.format_sequence_inner(type_, checker)
elif isinstance(type_, uper.SequenceOf):
return self.format_sequence_of_inner(type_, checker)
elif isinstance(type_, uper.Choice):
return self.format_choice_inner(type_, checker)
elif isinstance(type_, uper.OctetString):
return self.format_octet_string_inner(type_, checker)
elif isinstance(type_, uper.BitString):
return self.format_bit_string_inner(type_, checker)
elif isinstance(type_, uper.Enumerated):
return self.format_enumerated_inner(type_)
elif isinstance(type_, uper.Null):
return self.format_null_inner()
else:
return [], []
def format_integer_inner(self, type_, checker):
type_name = self.format_type_name(checker.minimum, checker.maximum)
suffix = type_name[:-2]
location = self.location_inner()
if type_.number_of_bits in [8, 16, 32, 64] and \
checker.minimum in [0, -128, -32768, -2147483648, -9223372036854775808]:
return (
[
'encoder_append_{}(encoder_p, src_p->{});'.format(
suffix,
location)
],
[
'dst_p->{} = decoder_read_{}(decoder_p);'.format(location,
suffix)
]
)
else:
return (
[
'encoder_append_non_negative_binary_integer(',
' encoder_p,',
' (uint64_t)(src_p->{} - {}),'.format(location, checker.minimum),
' {});'.format(type_.number_of_bits)
],
[
'dst_p->{} = ({})decoder_read_non_negative_binary_integer('.format(
location,
type_name),
' decoder_p,',
' {});'.format(type_.number_of_bits),
'dst_p->{} += {};'.format(location, checker.minimum)
]
)
def format_bit_string_inner(self, type_, checker):
location = self.location_inner()
max_value = 2 ** checker.minimum - 1
type_name = self.format_type_name(max_value, max_value)
return (
[
'encoder_append_non_negative_binary_integer(',
' encoder_p,',
' (uint64_t)(src_p->{}),'.format(location),
' {});'.format(type_.maximum)
],
[
'dst_p->{} = ({})decoder_read_non_negative_binary_integer('.format(
location,
type_name),
' decoder_p,',
' {});'.format(type_.maximum)
]
)
def format_boolean_inner(self):
return (
[
'encoder_append_bool(encoder_p, src_p->{});'.format(
self.location_inner())
],
[
'dst_p->{} = decoder_read_bool(decoder_p);'.format(
self.location_inner())
]
)
def format_real_inner(self):
return [], []
def format_sequence_inner(self, type_, checker):
encode_lines = []
decode_lines = []
member_name_to_is_present = {}
if type_.additions is not None:
if len(type_.additions) > 0:
if_line = 'if({}) {{'.format(self.get_addition_present_condition(type_))
encode_lines.extend(textwrap.wrap(if_line, 120,
subsequent_indent=' ' * len('if(')))
encode_lines.append(' encoder_abort(encoder_p, EINVAL);')
encode_lines.append(' return;')
encode_lines.append('}')
encode_lines.append('encoder_append_bool(encoder_p, false);')
if len(type_.additions) > 0:
unique_extension_present = \
self.add_unique_decode_variable('bool {};', 'extension_is_present')
decode_lines.append(
'extension_is_present = decoder_read_bool(decoder_p);')
else:
decode_lines.append('decoder_read_bool(decoder_p);')
for member in type_.root_members:
if member.optional:
name = '{}is_{}_present'.format(self.location_inner('', '.'),
canonical(member.name))
encode_lines.append(
'encoder_append_bool(encoder_p, src_p->{});'.format(
name))
decode_lines.append(
'dst_p->{} = decoder_read_bool(decoder_p);'.format(
name))
elif member.default is not None:
unique_is_present = self.add_unique_decode_variable('bool {};',
'is_present')
member_name_to_is_present[member.name] = unique_is_present
if self.is_buffer_type(member):
default_variable = canonical(member.name) + '_default'
encode_lines += [
'encoder_append_bool(encoder_p, (memcmp(src_p->{}{}.buf, {}, sizeof({})) != 0) ||'.format(
self.location_inner('', '.'),
canonical(member.name),
default_variable,
default_variable),
' (src_p->{}{}.length != sizeof({})));'.format(
self.location_inner('', '.'),
canonical(member.name),
default_variable)
]
else:
encode_lines.append(
'encoder_append_bool(encoder_p, src_p->{}{}{} != {});'.format(
self.location_inner('', '.'),
canonical(member.name),
'.value' if self.is_complex_user_type(member) else '',
self.format_default(member)))
decode_lines.append(
'{} = decoder_read_bool(decoder_p);'.format(
unique_is_present))
for member in type_.root_members:
(member_encode_lines,
member_decode_lines) = self.format_sequence_inner_member(
member,
checker,
member_name_to_is_present)
encode_lines += member_encode_lines
decode_lines += member_decode_lines
if type_.additions is not None and len(type_.additions) > 0:
decode_lines.append('if({}) {{'.format(unique_extension_present))
decode_lines.append(' decoder_abort(decoder_p, EINVAL);')
decode_lines.append(' return;')
decode_lines.append('}')
return encode_lines, decode_lines
def format_octet_string_inner(self, type_, checker):
location = self.location_inner('', '.')
if checker.maximum < 256:
length_type = 'uint8_t'
else:
length_type = 'uint32_t'
if checker.minimum == checker.maximum:
encode_lines = [
'encoder_append_bytes(encoder_p,',
' &src_p->{}buf[0],'.format(location),
' {});'.format(checker.maximum)
]
decode_lines = [
'decoder_read_bytes(decoder_p,',
' &dst_p->{}buf[0],'.format(location),
' {});'.format(checker.maximum)
]
else:
encode_lines = [
'encoder_append_non_negative_binary_integer(',
' encoder_p,',
' src_p->{}length - {}u,'.format(location, checker.minimum),
' {});'.format(type_.number_of_bits),
'encoder_append_bytes(encoder_p,',
' &src_p->{}buf[0],'.format(location),
' src_p->{}length);'.format(location)
]
decode_lines = [
'dst_p->{}length = ({})decoder_read_non_negative_binary_integer('.format(
location,
length_type),
' decoder_p,',
' {});'.format(type_.number_of_bits),
'dst_p->{}length += {}u;'.format(location, checker.minimum)
]
if not does_bits_match_range(type_.number_of_bits,
checker.minimum,
checker.maximum):
decode_lines += [
'',
'if (dst_p->{}length > {}u) {{'.format(location, checker.maximum),
' decoder_abort(decoder_p, EBADLENGTH);',
'',
' return;',
'}',
''
]
decode_lines += [
'decoder_read_bytes(decoder_p,',
' &dst_p->{}buf[0],'.format(location),
' dst_p->{}length);'.format(location)
]
return encode_lines, decode_lines
def format_user_type_inner(self, type_name, module_name):
module_name_snake = camel_to_snake_case(module_name)
type_name_snake = camel_to_snake_case(type_name)
prefix = '{}_{}_{}'.format(self.namespace,
module_name_snake,
type_name_snake)
encode_lines = [
'{}_encode_inner(encoder_p, &src_p->{});'.format(
prefix,
self.location_inner())
]
decode_lines = [
'{}_decode_inner(decoder_p, &dst_p->{});'.format(
prefix,
self.location_inner())
]
return encode_lines, decode_lines
def format_choice_inner(self, type_, checker):
encode_lines = []
decode_lines = []
type_name = self.format_type_name(0, max(type_.root_index_to_member))
unique_choice = self.add_unique_decode_variable(
'{} {{}};'.format(type_name),
'choice')
choice = '{}choice'.format(self.location_inner('', '.'))
for member in type_.root_index_to_member.values():
member_checker = self.get_member_checker(checker,
member.name)
with self.asn1_members_backtrace_push(canonical(member.name)):
with self.c_members_backtrace_push('value'):
with self.c_members_backtrace_push(canonical(member.name)):
choice_encode_lines, choice_decode_lines = self.format_type_inner(
member,
member_checker)
index = type_.root_name_to_index[member.name]
choice_encode_lines = [
'encoder_append_non_negative_binary_integer(encoder_p, {}, {});'.format(
index,
type_.root_number_of_bits)
] + choice_encode_lines + [
'break;'
]
encode_lines += [
'case {}_choice_{}_e:'.format(self.location, canonical(member.name))
] + indent_lines(choice_encode_lines) + [
''
]
choice_decode_lines = [
'dst_p->{} = {}_choice_{}_e;'.format(choice,
self.location,
canonical(member.name))
] + choice_decode_lines + [
'break;'
]
decode_lines += [
'case {}:'.format(index)
] + indent_lines(choice_decode_lines) + [
''
]
encode_lines = [
'',
'switch (src_p->{}) {{'.format(choice),
''
] + encode_lines + [
'default:',
' encoder_abort(encoder_p, EBADCHOICE);',
' break;',
'}',
''
]
decode_lines = [
'{} = ({})decoder_read_non_negative_binary_integer(decoder_p, {});'.format(
unique_choice,
type_name,
type_.root_number_of_bits),
'',
'switch ({}) {{'.format(unique_choice),
''
] + decode_lines + [
'default:',
' decoder_abort(decoder_p, EBADCHOICE);',
' break;',
'}',
''
]
return encode_lines, decode_lines
def format_enumerated_inner(self, type_):
type_name = self.format_type_name(0, max(type_.root_data_to_value.values()))
unique_value = self.add_unique_variable(
'{} {{}};'.format(type_name),
'value')
location = self.location_inner()
value_mapping_required = any([(type_.root_data_to_index[data]
!= type_.root_data_to_value[data])
for data in type_.root_data_to_index])
if value_mapping_required:
encode_lines = ['switch (src_p->{}) {{'.format(location)]
for data, _ in self.get_enumerated_values(type_):
encode_lines += [
'case {}_{}_e:'.format(self.location, data),
' {} = {};'.format(unique_value, type_.root_data_to_index[data]),
' break;']
encode_lines += [
'default:',
' encoder_abort(encoder_p, EBADENUM);',
' return;',
'}']
else:
encode_lines = ['{} = src_p->{};'.format(unique_value, location)]
encode_lines.append('encoder_append_non_negative_binary_integer(encoder_p, '
'{}, {});'.format(unique_value, type_.root_number_of_bits))
decode_lines = [
'{} = ({})decoder_read_non_negative_binary_integer('
'decoder_p, {});'.format(unique_value,
type_name,
type_.root_number_of_bits)
]
if bin(len(self.get_enumerated_values(type_))).count('1') != 1 and (not
value_mapping_required):
decode_lines += [
'',
'if ({} > {}u) {{'.format(unique_value,
len(self.get_enumerated_values(type_)) - 1),
' decoder_abort(decoder_p, EBADENUM);',
'',
' return;',
'}',
''
]
if value_mapping_required:
decode_lines.append('switch ({}) {{'.format(unique_value))
for data, _ in self.get_enumerated_values(type_):
decode_lines.append('case {}:'.format(type_.root_data_to_index[data]))
decode_lines.append(' dst_p->{} = {}_{}_e;'.format(location,
self.location,
data))
decode_lines.append(' break;')
decode_lines += [
'default:',
' decoder_abort(decoder_p, EBADENUM);',
' return;',
'}']
else:
decode_lines += [
'dst_p->{} = (enum {}_e){};'.format(location,
self.location,
unique_value)
]
return encode_lines, decode_lines
def format_null_inner(self):
return (
[
'(void)encoder_p;',
'(void)src_p;'
],
[
'(void)decoder_p;',
'(void)dst_p;'
]
)
def format_sequence_of_inner(self, type_, checker):
type_name = self.format_type_name(0, checker.maximum)
unique_i = self.add_unique_variable('{} {{}};'.format(type_name),
'i')
with self.c_members_backtrace_push('elements[{}]'.format(unique_i)):
encode_lines, decode_lines = self.format_type_inner(
type_.element_type,
checker.element_type)
if checker.minimum == checker.maximum:
first_encode_lines = first_decode_lines = [
'',
'for ({0} = 0; {0} < {1}; {0}++) {{'.format(
unique_i,
checker.maximum)
]
else:
location = self.location_inner('', '.')
first_encode_lines = [
'encoder_append_non_negative_binary_integer(',
' encoder_p,',
' src_p->{}length - {}u,'.format(location, checker.minimum),
' {});'.format(type_.number_of_bits),
'',
'for ({0} = 0; {0} < src_p->{1}length; {0}++) {{'.format(
unique_i,
location)
]
first_decode_lines = [
'dst_p->{}length = ({})decoder_read_non_negative_binary_integer('.format(
location,
type_name),
' decoder_p,',
' {});'.format(type_.number_of_bits),
'dst_p->{}length += {}u;'.format(location, checker.minimum),
''
]
if not does_bits_match_range(type_.number_of_bits,
checker.minimum,
checker.maximum):
first_decode_lines += [
'if (dst_p->{}length > {}u) {{'.format(location, checker.maximum),
' decoder_abort(decoder_p, EBADLENGTH);',
'',
' return;',
'}',
''
]
first_decode_lines += [
'for ({0} = 0; {0} < dst_p->{1}length; {0}++) {{'.format(
unique_i,
location)
]
encode_lines = first_encode_lines + indent_lines(encode_lines) + ['}', '']
decode_lines = first_decode_lines + indent_lines(decode_lines) + ['}', '']
return encode_lines, decode_lines
def format_type_inner(self, type_, checker):
if isinstance(type_, uper.Integer):
return self.format_integer_inner(type_, checker)
elif isinstance(type_, uper.Real):
return self.format_real_inner()
elif isinstance(type_, uper.Null):
return [], []
elif isinstance(type_, uper.Boolean):
return self.format_boolean_inner()
elif is_user_type(type_):
return self.format_user_type_inner(type_.type_name,
type_.module_name)
elif isinstance(type_, uper.OctetString):
return self.format_octet_string_inner(type_, checker)
elif isinstance(type_, uper.Sequence):
return self.format_sequence_inner(type_, checker)
elif isinstance(type_, uper.Choice):
return self.format_choice_inner(type_, checker)
elif isinstance(type_, uper.SequenceOf):
return self.format_sequence_of_inner(type_, checker)
elif isinstance(type_, uper.Enumerated):
return self.format_enumerated_inner(type_)
elif isinstance(type_, uper.BitString):
return self.format_bit_string_inner(type_, checker)
else:
raise self.error(type_)
def is_complex_user_type(self, type_):
return is_user_type(type_) and \
not isinstance(type_, (uper.Integer, uper.Boolean, uper.Real, uper.Null))
def is_buffer_type(self, type_):
return isinstance(type_, uper.OctetString)
def generate_helpers(self, definitions):
helpers = []
for pattern, definition in functions:
is_in_helpers = any([pattern in helper for helper in helpers])
if pattern in definitions or is_in_helpers:
helpers.insert(0, definition)
return [ENCODER_AND_DECODER_STRUCTS] + helpers + ['']
def generate(compiled, namespace):
return _Generator(namespace).generate(compiled)
asn1tools-0.169.0/asn1tools/source/c/uper_functions.py 0000664 0000000 0000000 00000025526 15245442746 0022723 0 ustar 00root root 0000000 0000000 """Functions required by the UPER C code generator
"""
from .utils import ENCODER_ABORT
from .utils import DECODER_ABORT
ENCODER_INIT = '''\
static void encoder_init(struct encoder_t *self_p,
uint8_t *buf_p,
size_t size)
{
self_p->buf_p = buf_p;
self_p->size = (8 * (ssize_t)size);
self_p->pos = 0;
}\
'''
ENCODER_GET_RESULT = '''
static ssize_t encoder_get_result(const struct encoder_t *self_p)
{
if (self_p->size >= 0) {
return ((self_p->pos + 7) / 8);
} else {
return (self_p->pos);
}
}\
'''
ENCODER_ALLOC = '''
static ssize_t encoder_alloc(struct encoder_t *self_p,
size_t size)
{
ssize_t pos;
if ((self_p->pos + (ssize_t)size) <= self_p->size) {
pos = self_p->pos;
self_p->pos += (ssize_t)size;
} else {
pos = -ENOMEM;
encoder_abort(self_p, ENOMEM);
}
return (pos);
}\
'''
ENCODER_APPEND_BIT = '''
static void encoder_append_bit(struct encoder_t *self_p,
int value)
{
ssize_t pos;
pos = encoder_alloc(self_p, 1);
if (pos < 0) {
return;
}
if ((pos % 8) == 0) {
self_p->buf_p[pos / 8] = 0;
}
self_p->buf_p[pos / 8] |= (uint8_t)(value << (7 - (pos % 8)));
}\
'''
ENCODER_APPEND_BYTES = '''
static void encoder_append_bytes(struct encoder_t *self_p,
const uint8_t *buf_p,
size_t size)
{
size_t i;
ssize_t pos;
size_t byte_pos;
size_t pos_in_byte;
pos = encoder_alloc(self_p, 8u * size);
if (pos < 0) {
return;
}
byte_pos = ((size_t)pos / 8u);
pos_in_byte = ((size_t)pos % 8u);
if (pos_in_byte == 0u) {
(void)memcpy(&self_p->buf_p[byte_pos], buf_p, size);
} else {
for (i = 0; i < size; i++) {
self_p->buf_p[byte_pos + i] |= (buf_p[i] >> pos_in_byte);
self_p->buf_p[byte_pos + i + 1] = (buf_p[i] << (8u - pos_in_byte));
}
}
}\
'''
ENCODER_APPEND_UINT8 = '''
static void encoder_append_uint8(struct encoder_t *self_p,
uint8_t value)
{
uint8_t buf[1];
buf[0] = (uint8_t)value;
encoder_append_bytes(self_p, &buf[0], sizeof(buf));
}\
'''
ENCODER_APPEND_UINT16 = '''
static void encoder_append_uint16(struct encoder_t *self_p,
uint16_t value)
{
uint8_t buf[2];
buf[0] = (uint8_t)(value >> 8);
buf[1] = (uint8_t)value;
encoder_append_bytes(self_p, &buf[0], sizeof(buf));
}\
'''
ENCODER_APPEND_UINT32 = '''
static void encoder_append_uint32(struct encoder_t *self_p,
uint32_t value)
{
uint8_t buf[4];
buf[0] = (uint8_t)(value >> 24);
buf[1] = (uint8_t)(value >> 16);
buf[2] = (uint8_t)(value >> 8);
buf[3] = (uint8_t)value;
encoder_append_bytes(self_p, &buf[0], sizeof(buf));
}\
'''
ENCODER_APPEND_UINT64 = '''
static void encoder_append_uint64(struct encoder_t *self_p,
uint64_t value)
{
uint8_t buf[8];
buf[0] = (uint8_t)(value >> 56);
buf[1] = (uint8_t)(value >> 48);
buf[2] = (uint8_t)(value >> 40);
buf[3] = (uint8_t)(value >> 32);
buf[4] = (uint8_t)(value >> 24);
buf[5] = (uint8_t)(value >> 16);
buf[6] = (uint8_t)(value >> 8);
buf[7] = (uint8_t)value;
encoder_append_bytes(self_p, &buf[0], sizeof(buf));
}\
'''
ENCODER_APPEND_INT8 = '''
static void encoder_append_int8(struct encoder_t *self_p,
int8_t value)
{
encoder_append_uint8(self_p, (uint8_t)value + 128);
}\
'''
ENCODER_APPEND_INT16 = '''
static void encoder_append_int16(struct encoder_t *self_p,
int16_t value)
{
encoder_append_uint16(self_p, (uint16_t)value + 32768);
}\
'''
ENCODER_APPEND_INT32 = '''
static void encoder_append_int32(struct encoder_t *self_p,
int32_t value)
{
encoder_append_uint32(self_p, (uint32_t)value + 2147483648);
}\
'''
ENCODER_APPEND_INT64 = '''
static void encoder_append_int64(struct encoder_t *self_p,
int64_t value)
{
uint64_t u64_value;
u64_value = (uint64_t)value;
u64_value += 9223372036854775808ull;
encoder_append_uint64(self_p, u64_value);
}\
'''
ENCODER_APPEND_BOOL = '''
static void encoder_append_bool(struct encoder_t *self_p, bool value)
{
encoder_append_bit(self_p, value ? 1 : 0);
}\
'''
ENCODER_APPEND_NON_NEGATIVE_BINARY_INTEGER = '''
static void encoder_append_non_negative_binary_integer(struct encoder_t *self_p,
uint64_t value,
size_t size)
{
size_t i;
for (i = 0; i < size; i++) {
encoder_append_bit(self_p, (value >> (size - i - 1)) & 1);
}
}\
'''
DECODER_INIT = '''
static void decoder_init(struct decoder_t *self_p,
const uint8_t *buf_p,
size_t size)
{
self_p->buf_p = buf_p;
self_p->size = (8 * (ssize_t)size);
self_p->pos = 0;
}\
'''
DECODER_GET_RESULT = '''
static ssize_t decoder_get_result(const struct decoder_t *self_p)
{
if (self_p->size >= 0) {
return ((self_p->pos + 7) / 8);
} else {
return (self_p->pos);
}
}\
'''
DECODER_FREE = '''
static ssize_t decoder_free(struct decoder_t *self_p,
size_t size)
{
ssize_t pos;
if ((self_p->pos + (ssize_t)size) <= self_p->size) {
pos = self_p->pos;
self_p->pos += (ssize_t)size;
} else {
pos = -EOUTOFDATA;
decoder_abort(self_p, EOUTOFDATA);
}
return (pos);
}\
'''
DECODER_READ_BIT = '''
static int decoder_read_bit(struct decoder_t *self_p)
{
ssize_t pos;
int value;
pos = decoder_free(self_p, 1);
if (pos >= 0) {
value = ((self_p->buf_p[pos / 8] >> (7 - (pos % 8))) & 1);
} else {
value = 0;
}
return (value);
}\
'''
DECODER_READ_BYTES = '''
static void decoder_read_bytes(struct decoder_t *self_p,
uint8_t *buf_p,
size_t size)
{
size_t i;
ssize_t pos;
size_t byte_pos;
size_t pos_in_byte;
pos = decoder_free(self_p, 8u * size);
if (pos < 0) {
return;
}
byte_pos = ((size_t)pos / 8u);
pos_in_byte = ((size_t)pos % 8u);
if (pos_in_byte == 0) {
(void)memcpy(buf_p, &self_p->buf_p[byte_pos], size);
} else {
for (i = 0; i < size; i++) {
buf_p[i] = (self_p->buf_p[byte_pos + i] << pos_in_byte);
buf_p[i] |= (self_p->buf_p[byte_pos + i + 1] >> (8u - pos_in_byte));
}
}
}\
'''
DECODER_READ_UINT8 = '''
static uint8_t decoder_read_uint8(struct decoder_t *self_p)
{
uint8_t value = 0;
decoder_read_bytes(self_p, &value, sizeof(value));
return (value);
}\
'''
DECODER_READ_UINT16 = '''
static uint16_t decoder_read_uint16(struct decoder_t *self_p)
{
uint8_t buf[2];
decoder_read_bytes(self_p, &buf[0], sizeof(buf));
return (((uint16_t)buf[0] << 8) | (uint16_t)buf[1]);
}\
'''
DECODER_READ_UINT32 = '''
static uint32_t decoder_read_uint32(struct decoder_t *self_p)
{
uint8_t buf[4];
decoder_read_bytes(self_p, &buf[0], sizeof(buf));
return (((uint32_t)buf[0] << 24)
| ((uint32_t)buf[1] << 16)
| ((uint32_t)buf[2] << 8)
| (uint32_t)buf[3]);
}\
'''
DECODER_READ_UINT64 = '''
static uint64_t decoder_read_uint64(struct decoder_t *self_p)
{
uint8_t buf[8];
decoder_read_bytes(self_p, &buf[0], sizeof(buf));
return (((uint64_t)buf[0] << 56)
| ((uint64_t)buf[1] << 48)
| ((uint64_t)buf[2] << 40)
| ((uint64_t)buf[3] << 32)
| ((uint64_t)buf[4] << 24)
| ((uint64_t)buf[5] << 16)
| ((uint64_t)buf[6] << 8)
| (uint64_t)buf[7]);
}\
'''
DECODER_READ_INT8 = '''
static int8_t decoder_read_int8(struct decoder_t *self_p)
{
int8_t value;
value = (int8_t)decoder_read_uint8(self_p);
value -= 128;
return (value);
}\
'''
DECODER_READ_INT16 = '''
static int16_t decoder_read_int16(struct decoder_t *self_p)
{
int16_t value;
value = (int16_t)decoder_read_uint16(self_p);
value -= 32768;
return (value);
}\
'''
DECODER_READ_INT32 = '''
static int32_t decoder_read_int32(struct decoder_t *self_p)
{
int32_t value;
value = (int32_t)decoder_read_uint32(self_p);
value -= 2147483648;
return (value);
}\
'''
DECODER_READ_INT64 = '''
static int64_t decoder_read_int64(struct decoder_t *self_p)
{
uint64_t value;
value = decoder_read_uint64(self_p);
value -= 9223372036854775808ull;
return ((int64_t)value);
}\
'''
DECODER_READ_BOOL = '''
static bool decoder_read_bool(struct decoder_t *self_p)
{
return (decoder_read_bit(self_p) != 0);
}\
'''
DECODER_READ_NON_NEGATIVE_BINARY_INTEGER = '''
static uint64_t decoder_read_non_negative_binary_integer(struct decoder_t *self_p,
size_t size)
{
size_t i;
uint64_t value;
value = 0;
for (i = 0; i < size; i++) {
value <<= 1;
value |= (uint64_t)decoder_read_bit(self_p);
}
return (value);
}\
'''
functions = [
(
'decoder_read_non_negative_binary_integer(',
DECODER_READ_NON_NEGATIVE_BINARY_INTEGER
),
('decoder_read_bool(', DECODER_READ_BOOL),
('decoder_read_int64(', DECODER_READ_INT64),
('decoder_read_int32(', DECODER_READ_INT32),
('decoder_read_int16(', DECODER_READ_INT16),
('decoder_read_int8(', DECODER_READ_INT8),
('decoder_read_uint64(', DECODER_READ_UINT64),
('decoder_read_uint32(', DECODER_READ_UINT32),
('decoder_read_uint16(', DECODER_READ_UINT16),
('decoder_read_uint8(', DECODER_READ_UINT8),
('decoder_read_bytes(', DECODER_READ_BYTES),
('decoder_read_bit(', DECODER_READ_BIT),
('decoder_free(', DECODER_FREE),
('decoder_abort(', DECODER_ABORT),
('decoder_get_result(', DECODER_GET_RESULT),
('decoder_init(', DECODER_INIT),
(
'encoder_append_non_negative_binary_integer(',
ENCODER_APPEND_NON_NEGATIVE_BINARY_INTEGER
),
('encoder_append_bool(', ENCODER_APPEND_BOOL),
('encoder_append_int64(', ENCODER_APPEND_INT64),
('encoder_append_int32(', ENCODER_APPEND_INT32),
('encoder_append_int16(', ENCODER_APPEND_INT16),
('encoder_append_int8(', ENCODER_APPEND_INT8),
('encoder_append_uint64(', ENCODER_APPEND_UINT64),
('encoder_append_uint32(', ENCODER_APPEND_UINT32),
('encoder_append_uint16(', ENCODER_APPEND_UINT16),
('encoder_append_uint8(', ENCODER_APPEND_UINT8),
('encoder_append_bytes(', ENCODER_APPEND_BYTES),
('encoder_append_bit(', ENCODER_APPEND_BIT),
('encoder_alloc(', ENCODER_ALLOC),
('encoder_abort(', ENCODER_ABORT),
('encoder_get_result(', ENCODER_GET_RESULT),
('encoder_init(', ENCODER_INIT)
]
asn1tools-0.169.0/asn1tools/source/c/utils.py 0000664 0000000 0000000 00000066733 15245442746 0021025 0 ustar 00root root 0000000 0000000 import re
from operator import itemgetter
from ...errors import Error
TYPE_DECLARATION_FMT = '''\
/**
* Type {type_name} in module {module_name}.
*/
{helper_types}\
struct {namespace}_{module_name_snake}_{type_name_snake}_t {{
{members}
}};
'''
DECLARATION_FMT = '''\
/**
* Encode type {type_name} defined in module {module_name}.
*
* @param[out] dst_p Buffer to encode into.
* @param[in] size Size of dst_p.
* @param[in] src_p Data to encode.
*
* @return Encoded data length or negative error code.
*/
ssize_t {namespace}_{module_name_snake}_{type_name_snake}_encode(
uint8_t *dst_p,
size_t size,
const struct {namespace}_{module_name_snake}_{type_name_snake}_t *src_p);
/**
* Decode type {type_name} defined in module {module_name}.
*
* @param[out] dst_p Decoded data.
* @param[in] src_p Data to decode.
* @param[in] size Size of src_p.
*
* @return Number of bytes decoded or negative error code.
*/
ssize_t {namespace}_{module_name_snake}_{type_name_snake}_decode(
struct {namespace}_{module_name_snake}_{type_name_snake}_t *dst_p,
const uint8_t *src_p,
size_t size);
'''
DEFINITION_INNER_FMT = '''\
static void {namespace}_{module_name_snake}_{type_name_snake}_encode_inner(
struct encoder_t *encoder_p,
const struct {namespace}_{module_name_snake}_{type_name_snake}_t *src_p)
{{
{encode_body}\
}}
static void {namespace}_{module_name_snake}_{type_name_snake}_decode_inner(
struct decoder_t *decoder_p,
struct {namespace}_{module_name_snake}_{type_name_snake}_t *dst_p)
{{
{decode_body}\
}}
'''
DEFINITION_FMT = '''\
ssize_t {namespace}_{module_name_snake}_{type_name_snake}_encode(
uint8_t *dst_p,
size_t size,
const struct {namespace}_{module_name_snake}_{type_name_snake}_t *src_p)
{{
struct encoder_t encoder;
encoder_init(&encoder, dst_p, size);
{namespace}_{module_name_snake}_{type_name_snake}_encode_inner(&encoder, src_p);
return (encoder_get_result(&encoder));
}}
ssize_t {namespace}_{module_name_snake}_{type_name_snake}_decode(
struct {namespace}_{module_name_snake}_{type_name_snake}_t *dst_p,
const uint8_t *src_p,
size_t size)
{{
struct decoder_t decoder;
decoder_init(&decoder, src_p, size);
{namespace}_{module_name_snake}_{type_name_snake}_decode_inner(&decoder, dst_p);
return (decoder_get_result(&decoder));
}}
'''
ENCODER_AND_DECODER_STRUCTS = '''\
struct encoder_t {
uint8_t *buf_p;
ssize_t size;
ssize_t pos;
};
struct decoder_t {
const uint8_t *buf_p;
ssize_t size;
ssize_t pos;
};
'''
ENCODER_ABORT = '''
static void encoder_abort(struct encoder_t *self_p,
ssize_t error)
{
if (self_p->size >= 0) {
self_p->size = -error;
self_p->pos = -error;
}
}\
'''
DECODER_ABORT = '''
static void decoder_abort(struct decoder_t *self_p,
ssize_t error)
{
if (self_p->size >= 0) {
self_p->size = -error;
self_p->pos = -error;
}
}\
'''
class _MembersBacktracesContext(object):
def __init__(self, backtraces, member_name):
self.backtraces = backtraces
self.member_name = member_name
def __enter__(self):
for backtrace in self.backtraces:
backtrace.append(self.member_name)
def __exit__(self, *args):
for backtrace in self.backtraces:
backtrace.pop()
class _UserType(object):
def __init__(self,
type_name,
module_name,
type_declaration,
declaration,
definition_inner,
definition):
self.type_name = type_name
self.module_name = module_name
self.type_declaration = type_declaration
self.declaration = declaration
self.definition_inner = definition_inner
self.definition = definition
class Generator(object):
def __init__(self, namespace):
self.namespace = canonical(namespace)
self.asn1_members_backtrace = []
self.c_members_backtrace = []
self.module_name = None
self.type_name = None
self.helper_lines = []
self.base_variables = set()
self.used_suffixes_by_base_variables = {}
self.encode_variable_lines = []
self.decode_variable_lines = []
self.used_user_types = []
def reset_type(self):
self.helper_lines = []
self.base_variables = set()
self.used_suffixes_by_base_variables = {}
self.encode_variable_lines = []
self.decode_variable_lines = []
self.used_user_types = []
@property
def module_name_snake(self):
return camel_to_snake_case(self.module_name)
@property
def type_name_snake(self):
return camel_to_snake_case(self.type_name)
def type_length(self, minimum, maximum):
# Make sure it fits in 64 bits.
if minimum < -9223372036854775808:
raise self.error(
'{} does not fit in int64_t.'.format(minimum))
elif maximum > 18446744073709551615:
raise self.error(
'{} does not fit in uint64_t.'.format(maximum))
elif minimum < 0 and maximum > 9223372036854775807:
raise self.error(
'{} does not fit in int64_t.'.format(maximum))
# Calculate the number of bytes needed.
if minimum < -2147483648:
minimum_length = 64
elif minimum < -32768:
minimum_length = 32
elif minimum < -128:
minimum_length = 16
elif minimum < 0:
minimum_length = 8
else:
minimum_length = 0
if maximum > 4294967295:
maximum_length = 64
elif maximum > 65535:
maximum_length = 32
elif maximum > 255:
maximum_length = 16
elif maximum > 0:
maximum_length = 8
else:
maximum_length = 0
if minimum_length == maximum_length == 0:
length = 8
else:
length = max(minimum_length, maximum_length)
return length
@staticmethod
def value_length(value):
if value < 256:
length = 1
elif value < 65536:
length = 2
elif value < 16777216:
length = 3
elif value < 4294967296:
length = 4
else:
length = 8
return length
def format_type_name(self, minimum, maximum):
length = self.type_length(minimum, maximum)
type_name = 'int{}_t'.format(length)
if minimum >= 0:
type_name = 'u' + type_name
return type_name
def format_default_enumerated(self, type_):
if is_user_type(type_):
return '{}_{}_e'.format(self.get_user_type_prefix(type_.type_name,
type_.module_name),
type_.default)
else:
with self.members_backtrace_push(type_.name):
return '{}_{}_e'.format(self.location, type_.default)
def get_addition_present_condition(self, type_):
return ' || '.join(['src_p->{}is_{}_addition_present'.
format(self.location_inner('', '.'), addition.name)
for addition in type_.additions])
def get_named_number_values(self, type_):
if type_.named_bits is not None:
return sorted([(canonical(data), value)
for data, value in type_.named_bits],
key=itemgetter(1))
def get_user_type_prefix(self, type_name, module_name):
module_name_snake = camel_to_snake_case(module_name)
type_name_snake = camel_to_snake_case(type_name)
return '{}_{}_{}'.format(self.namespace,
module_name_snake,
type_name_snake)
@property
def location(self):
location = '{}_{}_{}'.format(self.namespace,
self.module_name_snake,
self.type_name_snake)
if self.asn1_members_backtrace:
location += '_{}'.format('_'.join(self.asn1_members_backtrace))
return location
def location_inner(self, default='value', end=''):
if self.c_members_backtrace:
return '.'.join(self.c_members_backtrace) + end
else:
return default
def location_error(self):
location = '{}.{}'.format(self.module_name, self.type_name)
if self.asn1_members_backtrace:
location += '.{}'.format('.'.join(self.asn1_members_backtrace))
return location
def members_backtrace_push(self, member_name):
backtraces = [
self.asn1_members_backtrace,
self.c_members_backtrace
]
return _MembersBacktracesContext(backtraces, member_name)
def asn1_members_backtrace_push(self, member_name):
backtraces = [self.asn1_members_backtrace]
return _MembersBacktracesContext(backtraces, member_name)
def c_members_backtrace_push(self, member_name):
backtraces = [self.c_members_backtrace]
return _MembersBacktracesContext(backtraces, member_name)
def get_member_checker(self, checker, name):
for member in checker.members:
if member.name == name:
return member
raise Error('No member checker found for {}.'.format(name))
def add_unique_variable(self, fmt, name, variable_lines=None):
if name in self.base_variables:
try:
suffix = self.used_suffixes_by_base_variables[name]
suffix += 1
except KeyError:
suffix = 2
self.used_suffixes_by_base_variables[name] = suffix
unique_name = '{}_{}'.format(name, suffix)
else:
self.base_variables.add(name)
unique_name = name
line = fmt.format(unique_name)
if variable_lines is None:
self.encode_variable_lines.append(line)
self.decode_variable_lines.append(line)
elif variable_lines == 'encode':
self.encode_variable_lines.append(line)
else:
self.decode_variable_lines.append(line)
return unique_name
def add_unique_encode_variable(self, fmt, name):
return self.add_unique_variable(fmt, name, 'encode')
def add_unique_decode_variable(self, fmt, name):
return self.add_unique_variable(fmt, name, 'decode')
def add_sequence_member(self, member, checker):
member_checker = self.get_member_checker(checker, member.name)
with self.members_backtrace_push(canonical(member.name)):
member_lines = self.format_type(member, member_checker)
if member_lines:
member_lines[-1] += ' {};'.format(canonical(member.name))
return member_lines
def error(self, message):
return Error('{}: {}'.format(self.location_error(), message))
def format_integer(self, checker):
if not checker.has_lower_bound():
raise self.error('INTEGER has no minimum value.')
if not checker.has_upper_bound():
raise self.error('INTEGER has no maximum value.')
type_name = self.format_type_name(checker.minimum, checker.maximum)
return [type_name]
def format_boolean(self):
return ['bool']
def format_octet_string(self, checker):
if not checker.has_upper_bound():
raise self.error('OCTET STRING has no maximum length.')
if checker.minimum == checker.maximum:
lines = []
elif checker.maximum < 256:
lines = [' uint8_t length;']
else:
lines = [' uint32_t length;']
return [
'struct {'
] + lines + [
' uint8_t buf[{}];'.format(checker.maximum),
'}'
]
def format_bit_string(self, type_, checker):
def get_value(value):
byte = (length - 1) - (value // 8)
bit = 7 - (value % 8)
return ('0x{:0' + str(length // 4) + 'x}').format(1 << (bit + byte * 8))
if checker.minimum != checker.maximum:
raise self.error('BIT STRING with variable SIZE not supported.')
if checker.minimum > 64:
raise self.error('BIT STRING with a length of more than 64 bits are not '
'supported.')
max_value = 2**checker.minimum - 1
length = self.value_length(max_value)
named_bits = self.get_named_number_values(type_)
type_name = self.format_type_name(max_value, max_value)
if named_bits is not None:
self.helper_lines += [
'static const {} {}_{} = {};'.format(type_name, self.location.upper(),
name.upper(), get_value(value))
for name, value in self.get_named_number_values(type_)
]
return [type_name]
def format_sequence(self, type_, checker):
lines = []
for member in type_.root_members:
if member.optional:
lines += ['bool is_{}_present;'.format(canonical(member.name))]
lines += self.add_sequence_member(member, checker)
if type_.additions is not None and len(type_.additions) > 0:
for addition in type_.additions:
lines += ['bool is_{}_addition_present;'.format(addition.name)]
lines += self.add_sequence_member(addition, checker)
return ['struct {'] + indent_lines(lines) + ['}']
def format_sequence_of(self, type_, checker):
if not checker.is_bound():
raise self.error('SEQUENCE OF has no maximum length.')
lines = self.format_type(type_.element_type, checker.element_type)
if lines:
lines[-1] += ' elements[{}];'.format(checker.maximum)
if checker.minimum == checker.maximum:
length_lines = []
elif checker.maximum < 256:
length_lines = ['uint8_t length;']
else:
length_lines = ['uint32_t length;']
return ['struct {'] + indent_lines(length_lines + lines) + ['}']
def format_enumerated(self, type_):
lines = ['enum {}_e'.format(self.location)]
values = [
' {}_{}_e = {}'.format(self.location, name, value)
for name, value in self.get_enumerated_values(type_)
]
self.helper_lines += [
'enum {}_e {{'.format(self.location)
] + join_lines(values, ',') + [
'};',
''
]
return lines
def format_choice(self, type_, checker):
lines = []
choices = []
for member in self.get_choice_members(type_):
member_checker = self.get_member_checker(checker,
member.name)
with self.members_backtrace_push(canonical(member.name)):
choice_lines = self.format_type(member, member_checker)
if choice_lines:
choice_lines[-1] += ' {};'.format(canonical(member.name))
lines += choice_lines
choices.append(' {}_choice_{}_e'.format(self.location,
canonical(member.name)))
self.helper_lines += [
'enum {}_choice_e {{'.format(self.location)
] + join_lines(choices, ',') + [
'};',
''
]
lines = [
'enum {}_choice_e choice;'.format(self.location),
'union {'
] + indent_lines(lines) + [
'} value;'
]
lines = ['struct {'] + indent_lines(lines) + ['}']
return lines
def format_user_type(self, type_name, module_name):
module_name_snake = camel_to_snake_case(module_name)
type_name_snake = camel_to_snake_case(type_name)
self.used_user_types.append((type_name, module_name))
return ['struct {}_{}_{}_t'.format(self.namespace,
module_name_snake,
type_name_snake)]
def format_sequence_inner_member(self,
member,
checker,
default_condition_by_member_name,
skip_when_not_present=True):
member_checker = self.get_member_checker(checker, member.name)
with self.members_backtrace_push(canonical(member.name)):
encode_lines, decode_lines = self.format_type_inner(
member,
member_checker)
location = self.location_inner('', '.')
if member.optional and skip_when_not_present:
is_present = '{}is_{}_present'.format(location, canonical(member.name))
encode_lines = [
'',
'if (src_p->{}) {{'.format(is_present)
] + indent_lines(encode_lines) + [
'}',
''
]
decode_lines = [
'',
'if (dst_p->{}) {{'.format(is_present)
] + indent_lines(decode_lines) + [
'}',
''
]
elif member.default is not None and skip_when_not_present:
name = '{}{}'.format(location, canonical(member.name))
if self.is_buffer_type(member):
default_value = '{{' + ', '.join(['0x%02X' % m for m in member.default]) + '}};'
default_variable = self.add_unique_variable('static const uint8_t {}[] = ' + default_value,
canonical(member.name) + '_default')
encode_lines = [
'',
'if ((memcmp(src_p->{}.buf, {}, sizeof({})) != 0) ||'.format(
name,
default_variable,
default_variable),
' (src_p->{}.length != sizeof({}))) {{'.format(
name,
default_variable)
] + indent_lines(encode_lines) + [
'}',
''
]
decode_lines = [
'',
'if ({}) {{'.format(default_condition_by_member_name[member.name])
] + indent_lines(decode_lines) + [
'} else {',
' memcpy(dst_p->{}.buf, {}, sizeof({}));'.format(
name,
default_variable,
default_variable),
' dst_p->{}.length = sizeof({});'.format(
name,
default_variable
),
'}',
''
]
else:
encode_lines = [
'',
'if (src_p->{}{} != {}) {{'.format(
name,
'.value' if self.is_complex_user_type(member) else '',
self.format_default(member))
] + indent_lines(encode_lines) + [
'}',
''
]
decode_lines = [
'',
'if ({}) {{'.format(default_condition_by_member_name[member.name])
] + indent_lines(decode_lines) + [
'} else {',
' dst_p->{}{} = {};'.format(
name,
'.value' if self.is_complex_user_type(member) else '',
self.format_default(member)),
'}',
''
]
return encode_lines, decode_lines
def generate_type_declaration(self, compiled_type):
type_ = compiled_type.type
checker = compiled_type.constraints_checker.type
lines = self.generate_type_declaration_process(type_, checker)
if not lines:
lines = ['uint8_t dummy;']
lines = indent_lines(lines)
if self.helper_lines:
self.helper_lines.append('')
return [
TYPE_DECLARATION_FMT.format(namespace=self.namespace,
module_name=self.module_name,
type_name=self.type_name,
module_name_snake=self.module_name_snake,
type_name_snake=self.type_name_snake,
helper_types='\n'.join(self.helper_lines),
members='\n'.join(lines))
]
def generate_declaration(self):
return DECLARATION_FMT.format(namespace=self.namespace,
module_name=self.module_name,
type_name=self.type_name,
module_name_snake=self.module_name_snake,
type_name_snake=self.type_name_snake)
def generate_definition(self):
return DEFINITION_FMT.format(namespace=self.namespace,
module_name_snake=self.module_name_snake,
type_name_snake=self.type_name_snake)
def generate_definition_inner(self, compiled_type):
encode_lines, decode_lines = self.generate_definition_inner_process(
compiled_type.type,
compiled_type.constraints_checker.type)
if self.encode_variable_lines:
encode_lines = self.encode_variable_lines + [''] + encode_lines
if self.decode_variable_lines:
decode_lines = self.decode_variable_lines + [''] + decode_lines
encode_lines = indent_lines(encode_lines) + ['']
decode_lines = indent_lines(decode_lines) + ['']
return DEFINITION_INNER_FMT.format(namespace=self.namespace,
module_name_snake=self.module_name_snake,
type_name_snake=self.type_name_snake,
encode_body='\n'.join(encode_lines),
decode_body='\n'.join(decode_lines))
def generate(self, compiled):
user_types = {}
user_type_dependencies = {}
for module_name, module in sorted(compiled.modules.items()):
self.module_name = module_name
for type_name, compiled_type in sorted(module.items()):
self.type_name = type_name
self.reset_type()
type_declaration = self.generate_type_declaration(compiled_type)
if not type_declaration:
continue
declaration = self.generate_declaration()
definition_inner = self.generate_definition_inner(compiled_type)
definition = self.generate_definition()
user_type = _UserType(type_name,
module_name,
type_declaration,
declaration,
definition_inner,
definition)
user_type_name_tuple = (user_type.type_name, user_type.module_name)
user_types[user_type_name_tuple] = user_type
user_type_dependencies[user_type_name_tuple] = self.used_user_types
user_type_sorted_names = topological_sort(user_type_dependencies)
type_declarations = []
declarations = []
definitions_inner = []
definitions = []
for user_type_name in user_type_sorted_names:
user_type = user_types[user_type_name]
type_declarations.extend(user_type.type_declaration)
declarations.append(user_type.declaration)
definitions_inner.append(user_type.definition_inner)
definitions.append(user_type.definition)
type_declarations = '\n'.join(type_declarations)
declarations = '\n'.join(declarations)
definitions = '\n'.join(definitions_inner + definitions)
helpers = '\n'.join(self.generate_helpers(definitions))
return type_declarations, declarations, helpers, definitions
def format_default(self, type_):
raise NotImplementedError('To be implemented by subclasses.')
def format_type(self, type_, checker):
raise NotImplementedError('To be implemented by subclasses.')
def format_type_inner(self, type_, checker):
raise NotImplementedError('To be implemented by subclasses.')
def get_enumerated_values(self, type_):
raise NotImplementedError('To be implemented by subclasses.')
def get_choice_members(self, type_):
raise NotImplementedError('To be implemented by subclasses.')
def generate_type_declaration_process(self, type_, checker):
raise NotImplementedError('To be implemented by subclasses.')
def generate_definition_inner_process(self, type_, checker):
raise NotImplementedError('To be implemented by subclasses.')
def generate_helpers(self, definitions):
raise NotImplementedError('To be implemented by subclasses.')
def is_complex_user_type(self, type_):
raise NotImplementedError('To be implemented by subclasses.')
def is_buffer_type(self, type_):
raise NotImplementedError('To be implemented by subclasses.')
def canonical(value):
"""Replace anything but 'a-z', 'A-Z' and '0-9' with '_'.
"""
return re.sub(r'[^a-zA-Z0-9]', '_', value)
def camel_to_snake_case(value):
value = re.sub(r'(.)([A-Z][a-z]+)', r'\1_\2', value)
value = re.sub(r'(_+)', '_', value)
value = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', value).lower()
value = canonical(value)
return value
def join_lines(lines, suffix):
return[line + suffix for line in lines[:-1]] + lines[-1:]
def is_user_type(type_):
return type_.module_name is not None
def strip_blank_lines(lines):
try:
while lines[0] == '':
del lines[0]
while lines[-1] == '':
del lines[-1]
except IndexError:
pass
stripped = []
for line in lines:
if line == '' and stripped[-1] == '':
continue
stripped.append(line)
return stripped
def indent_lines(lines):
indented_lines = []
for line in lines:
if line:
indented_line = 4 * ' ' + line
else:
indented_line = line
indented_lines.append(indented_line)
return strip_blank_lines(indented_lines)
def dedent_lines(lines):
return [line[4:] for line in lines]
def topological_sort(graph):
"""Topological sort algorithm to return a list of keys to a dictionary
of lists of dependencies. The returned keys define an order so
that all dependent items are in front of the originating item.
"""
def recurse(node, path):
if node not in path:
edges = graph[node]
for edge in edges:
if edge not in path:
path = recurse(edge, path)
path = path + [node]
return path
path = []
for node in sorted(graph):
path = recurse(node, path)
return path
asn1tools-0.169.0/asn1tools/source/rust/ 0000775 0000000 0000000 00000000000 15245442746 0020047 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/asn1tools/source/rust/__init__.py 0000664 0000000 0000000 00000001211 15245442746 0022153 0 ustar 00root root 0000000 0000000 import time
from ...version import __version__
from . import uper
SOURCE_FMT = '''\
//! This file was generated by asn1tools version {version} {date}.
{helpers}
{types_code}\
'''
def generate(compiled, codec):
"""Generate Rust source code from given compiled specification.
"""
date = time.ctime()
if codec == 'uper':
helpers, types_code = uper.generate(compiled)
else:
raise Exception()
source = SOURCE_FMT.format(version=__version__,
date=date,
helpers=helpers,
types_code=types_code)
return source
asn1tools-0.169.0/asn1tools/source/rust/uper.py 0000664 0000000 0000000 00000061245 15245442746 0021404 0 ustar 00root root 0000000 0000000 """Unaligned Packed Encoding Rules (UPER) Rust source code codec generator.
"""
from .utils import ENCODER_AND_DECODER_STRUCTS
from .utils import ENCODER_ABORT
from .utils import DECODER_ABORT
from .utils import Generator
from .utils import is_user_type
from .utils import indent_lines
from .utils import dedent_lines
from .utils import make_camel_case
from ...codecs import uper
ENCODER_INIT = '''\
fn new(dst: &'a mut [u8]) -> Encoder {
Encoder {
size: 8 * dst.len(),
buf: dst,
pos: 0,
error: None
}
}\
'''
ENCODER_GET_RESULT = '''
fn get_result(&self) -> Result {
if self.error.is_none() {
return Ok((self.pos + 7) / 8);
} else {
return Err(self.error.unwrap());
}
}\
'''
ENCODER_ALLOC = '''
fn alloc(&mut self, size: usize) -> Result {
if self.pos + size <= self.size {
let pos = self.pos;
self.pos += size;
Ok(pos)
} else {
self.abort(Error::OutOfMemory);
Err(())
}
}\
'''
ENCODER_APPEND_BIT = '''
fn append_bit(&mut self, value: u8) {
if let Ok(pos) = self.alloc(1) {
if pos % 8 == 0 {
self.buf[pos / 8] = 0;
}
self.buf[pos / 8] |= value << (7 - (pos % 8));
}
}\
'''
ENCODER_APPEND_BYTES = '''
fn append_bytes(&mut self, buf: &[u8]) {
if let Ok(pos) = self.alloc(8 * buf.len()) {
let byte_pos = pos / 8;
let pos_in_byte = pos % 8;
if pos_in_byte == 0 {
self.buf.get_mut(byte_pos..byte_pos + buf.len())
.unwrap()
.copy_from_slice(buf.get(0..buf.len()).unwrap());
} else {
for i in 0..buf.len() {
self.buf[byte_pos + i] |= buf[i] >> pos_in_byte;
self.buf[byte_pos + i + 1] = buf[i] << (8 - pos_in_byte);
}
}
}
}\
'''
ENCODER_APPEND_U8 = '''
fn append_u8(&mut self, value: u8) {
self.append_bytes(&value.to_be_bytes());
}\
'''
ENCODER_APPEND_U16 = '''
fn append_u16(&mut self, value: u16) {
self.append_bytes(&value.to_be_bytes());
}\
'''
ENCODER_APPEND_U32 = '''
fn append_u32(&mut self, value: u32) {
self.append_bytes(&value.to_be_bytes());
}\
'''
ENCODER_APPEND_U64 = '''
fn append_u64(&mut self, value: u64) {
self.append_bytes(&value.to_be_bytes());
}\
'''
ENCODER_APPEND_I8 = '''
fn append_i8(&mut self, value: i8) {
self.append_u8((value as u8).wrapping_add(128));
}\
'''
ENCODER_APPEND_I16 = '''
fn append_i16(&mut self, value: i16) {
self.append_u16((value as u16).wrapping_add(32768));
}\
'''
ENCODER_APPEND_I32 = '''
fn append_i32(&mut self, value: i32) {
self.append_u32((value as u32).wrapping_add(2147483648));
}\
'''
ENCODER_APPEND_I64 = '''
fn append_i64(&mut self, value: i64) {
self.append_u64((value as u64).wrapping_add(9223372036854775808));
}\
'''
ENCODER_APPEND_BOOL = '''
fn append_bool(&mut self, value: bool) {
self.append_bit(value as u8);
}\
'''
ENCODER_APPEND_NON_NEGATIVE_BINARY_INTEGER = '''
fn append_non_negative_binary_integer(&mut self, value: u64, size: usize) {
for i in 0..size {
self.append_bit((value >> (size - i - 1)) as u8 & 1);
}
}\
'''
DECODER_INIT = '''
fn new(src: &'a[u8]) -> Decoder {
Decoder {
buf: src,
size: 8 * src.len(),
pos: 0,
error: None
}
}\
'''
DECODER_GET_RESULT = '''
fn get_result(&self) -> Result {
if self.error.is_none() {
Ok((self.pos + 7) / 8)
} else {
Err(self.error.unwrap())
}
}\
'''
DECODER_FREE = '''
fn free(&mut self, size: usize) -> Result {
if self.pos + size <= self.size {
let pos = self.pos;
self.pos += size;
Ok(pos)
} else {
self.abort(Error::OutOfData);
Err(())
}
}\
'''
DECODER_READ_BIT = '''
fn read_bit(&mut self) -> u8 {
if let Ok(pos) = self.free(1) {
(self.buf[pos / 8] >> (7 - (pos % 8))) & 1
} else {
0
}
}\
'''
DECODER_READ_BYTES = '''
fn read_bytes(&mut self, buf: &mut [u8]) {
if let Ok(pos) = self.free(8 * buf.len()) {
let byte_pos = pos / 8;
let pos_in_byte = pos % 8;
if pos_in_byte == 0 {
buf.copy_from_slice(
self.buf.get(byte_pos..byte_pos + buf.len()).unwrap());
} else {
for i in 0..buf.len() {
buf[i] = self.buf[byte_pos + i] << pos_in_byte;
buf[i] |= self.buf[byte_pos + i + 1] >> (8 - pos_in_byte);
}
}
}
}\
'''
DECODER_READ_U8 = '''
fn read_u8(&mut self) -> u8 {
let mut buf = [0; 1];
self.read_bytes(&mut buf);
u8::from_be_bytes(buf)
}\
'''
DECODER_READ_U16 = '''
fn read_u16(&mut self) -> u16 {
let mut buf = [0; 2];
self.read_bytes(&mut buf);
u16::from_be_bytes(buf)
}\
'''
DECODER_READ_U32 = '''
fn read_u32(&mut self) -> u32 {
let mut buf = [0; 4];
self.read_bytes(&mut buf);
u32::from_be_bytes(buf)
}\
'''
DECODER_READ_U64 = '''
fn read_u64(&mut self) -> u64 {
let mut buf = [0; 8];
self.read_bytes(&mut buf);
u64::from_be_bytes(buf)
}\
'''
DECODER_READ_I8 = '''
fn read_i8(&mut self) -> i8 {
self.read_u8().wrapping_sub(128) as i8
}\
'''
DECODER_READ_I16 = '''
fn read_i16(&mut self) -> i16 {
self.read_u16().wrapping_sub(32768) as i16
}\
'''
DECODER_READ_I32 = '''
fn read_i32(&mut self) -> i32 {
self.read_u32().wrapping_sub(2147483648) as i32
}\
'''
DECODER_READ_I64 = '''
fn read_i64(&mut self) -> i64 {
self.read_u64().wrapping_sub(9223372036854775808) as i64
}\
'''
DECODER_READ_BOOL = '''
fn read_bool(&mut self) -> bool {
self.read_bit() != 0
}\
'''
DECODER_READ_NON_NEGATIVE_BINARY_INTEGER = '''
fn read_non_negative_binary_integer(&mut self, size: usize) -> u64 {
let mut value: u64 = 0;
for _ in 0..size {
value <<= 1;
value |= self.read_bit() as u64;
}
value
}\
'''
def does_bits_match_range(number_of_bits, minimum, maximum):
return 2 ** number_of_bits == (maximum - minimum + 1)
class _Generator(Generator):
def format_real(self):
return []
def get_enumerated_values(self, type_):
return sorted(type_.root_data_to_index)
def get_choice_members(self, type_):
return type_.root_index_to_member.values()
def format_type(self, type_, checker):
if isinstance(type_, uper.Integer):
return self.format_integer(checker)
elif isinstance(type_, uper.Boolean):
return self.format_boolean()
elif isinstance(type_, uper.Real):
return self.format_real()
elif isinstance(type_, uper.Null):
return []
elif is_user_type(type_):
return self.format_user_type(type_.type_name,
type_.module_name)
elif isinstance(type_, uper.OctetString):
return self.format_octet_string(checker)
elif isinstance(type_, uper.Sequence):
return self.format_sequence(type_, checker)
elif isinstance(type_, uper.Choice):
return self.format_choice(type_, checker)
elif isinstance(type_, uper.SequenceOf):
return self.format_sequence_of(type_, checker)
elif isinstance(type_, uper.Enumerated):
return self.format_enumerated(type_)
else:
raise self.error(
"Unsupported type '{}'.".format(type_.type_name))
def generate_type_declaration_process(self, type_, checker):
if isinstance(type_, uper.Integer):
lines = self.format_integer(checker)
lines[0] += ' value;'
elif isinstance(type_, uper.Boolean):
lines = self.format_boolean()
lines[0] += ' value;'
elif isinstance(type_, uper.Real):
lines = self.format_real()
elif isinstance(type_, uper.Enumerated):
lines = self.format_enumerated(type_)
lines[0] += ' value;'
elif isinstance(type_, uper.Sequence):
lines = self.format_sequence(type_, checker)
elif isinstance(type_, uper.SequenceOf):
lines = self.format_sequence_of(type_, checker)[1:-1]
lines = dedent_lines(lines)
elif isinstance(type_, uper.Choice):
lines = self.format_choice(type_, checker)
elif isinstance(type_, uper.OctetString):
lines = self.format_octet_string(checker)[1:-1]
lines = dedent_lines(lines)
elif isinstance(type_, uper.Null):
lines = []
else:
raise self.error(
"Unsupported type '{}'.".format(type_.type_name))
return lines
def generate_definition_inner_process(self, type_, checker):
if isinstance(type_, uper.Integer):
return self.format_integer_inner(type_, checker)
elif isinstance(type_, uper.Boolean):
return self.format_boolean_inner()
elif isinstance(type_, uper.Real):
return self.format_real_inner()
elif isinstance(type_, uper.Sequence):
return self.format_sequence_inner(type_, checker)
elif isinstance(type_, uper.SequenceOf):
return self.format_sequence_of_inner(type_, checker)
elif isinstance(type_, uper.Choice):
return self.format_choice_inner(type_, checker)
elif isinstance(type_, uper.OctetString):
return self.format_octet_string_inner(type_, checker)
elif isinstance(type_, uper.Enumerated):
return self.format_enumerated_inner(type_)
elif isinstance(type_, uper.Null):
return self.format_null_inner()
else:
return [], []
def format_integer_inner(self, type_, checker):
type_name = self.format_type_name(checker.minimum, checker.maximum)
location = self.location_inner()
if (type_.number_of_bits % 8) == 0:
return (
[
'encoder.append_{}(self.{});'.format(
type_name,
location)
],
[
'self.{} = decoder.read_{}();'.format(location, type_name)
]
)
else:
return (
[
'encoder.append_non_negative_binary_integer(',
' (self.{} - {}) as u64,'.format(location, checker.minimum),
' {});'.format(type_.number_of_bits)
],
[
'self.{} = '
'decoder.read_non_negative_binary_integer({}) as {};'.format(
location,
type_.number_of_bits,
type_name),
'self.{} += {};'.format(location, checker.minimum)
]
)
def format_boolean_inner(self):
return (
[
'encoder.append_bool(self.{});'.format(
self.location_inner())
],
[
'self.{} = decoder.read_bool();'.format(
self.location_inner())
]
)
def format_real_inner(self):
return [], []
def format_sequence_inner(self, type_, checker):
encode_lines = []
decode_lines = []
member_name_to_is_present = {}
for member in type_.root_members:
if member.optional:
name = '{}is_{}_present'.format(self.location_inner('', '.'),
member.name)
encode_lines.append(
'encoder.append_bit(self.{} as u8);'.format(name))
decode_lines.append(
'self.{} = decoder.read_bit() != 0;'.format(
name))
elif member.default is not None:
unique_is_present = self.add_unique_variable('is_present')
member_name_to_is_present[member.name] = unique_is_present
encode_lines.append(
'encoder.append_bit((self.{}{} != {}) as u8);'.format(
self.location_inner('', '.'),
member.name,
member.default))
decode_lines.append(
'{} = decoder.read_bit() == 1;'.format(
unique_is_present))
for member in type_.root_members:
(member_encode_lines,
member_decode_lines) = self.format_sequence_inner_member(
member,
checker,
member_name_to_is_present)
encode_lines += member_encode_lines
decode_lines += member_decode_lines
return encode_lines, decode_lines
def format_octet_string_inner(self, type_, checker):
location = self.location_inner('', '.')
if checker.minimum == checker.maximum:
encode_lines = [
'encoder.append_bytes(&self.{}buf);'.format(location)
]
decode_lines = [
'decoder.read_bytes(&mut self.{}buf);'.format(location)
]
else:
encode_lines = [
'encoder.append_non_negative_binary_integer(',
' (self.{}length - {}) as u64,'.format(location,
checker.minimum),
' {});'.format(type_.number_of_bits),
'encoder.append_bytes(&self.{}buf,'.format(location),
' self.{}length);'.format(location)
]
decode_lines = [
'self.{}length = decoder.read_non_negative_binary_integer('.format(
location),
' {});'.format(type_.number_of_bits),
'self.{}length += {};'.format(location, checker.minimum)
]
if not does_bits_match_range(type_.number_of_bits,
checker.minimum,
checker.maximum):
decode_lines += [
'',
'if self.{}length > {} {{'.format(location, checker.maximum),
' decoder.abort(Error::BadLength);',
'',
' return;',
'}',
''
]
decode_lines += [
'decoder.read_bytes(&mut self.{}buf,'.format(location),
' self.{}length);'.format(location)
]
return encode_lines, decode_lines
def format_user_type_inner(self):
encode_lines = [
'self.{}.encode_inner(&mut encoder);'.format(
self.location_inner())
]
decode_lines = [
'self.{}.decode_inner(&mut decoder);'.format(
self.location_inner())
]
return encode_lines, decode_lines
def format_choice_inner(self, type_, checker):
encode_lines = []
decode_lines = []
unique_choice = self.add_unique_variable('choice')
choice = '{}choice'.format(self.location_inner('', '.'))
for member in type_.root_index_to_member.values():
member_checker = self.get_member_checker(checker,
member.name)
with self.asn1_members_backtrace_push(member.name):
with self.c_members_backtrace_push(member.name):
choice_encode_lines, choice_decode_lines = self.format_type_inner(
member,
member_checker)
index = type_.root_name_to_index[member.name]
choice_encode_lines = [
'encoder.append_non_negative_binary_integer({}, {});'.format(
index,
type_.root_number_of_bits)
] + choice_encode_lines
encode_lines += [
' {}({}) => {{'.format(make_camel_case(member.name),
unique_choice)
] + indent_lines(choice_encode_lines, 8) + [
' },'
]
choice_decode_lines = [
'self.{} = {}{};'.format(choice,
self.location,
make_camel_case(member.name))
] + choice_decode_lines
decode_lines += [
' {} => {{'.format(index)
] + indent_lines(choice_decode_lines, 8) + [
' },'
]
encode_lines = [
'',
'match self {'
] + encode_lines + [
' _ => encoder.abort(Error::BadChoice);',
'}',
''
]
decode_lines = [
'',
'match decoder.read_non_negative_binary_integer({}) {{'.format(
type_.root_number_of_bits)
] + decode_lines + [
' _ => decoder.abort(Error::BadChoice);',
'}',
''
]
return encode_lines, decode_lines
def format_enumerated_inner(self, type_):
return (
[
'encoder.append_non_negative_binary_integer('
'self.{}, {});'.format(self.location_inner(),
type_.root_number_of_bits)
],
[
'self.{} = decoder.read_non_negative_binary_integer('
'{});'.format(self.location_inner(),
type_.root_number_of_bits)
]
)
def format_null_inner(self):
return (
[
'(void)src_p;'
],
[
'(void)dst_p;'
]
)
def format_sequence_of_inner(self, type_, checker):
unique_i = self.add_unique_variable('i')
with self.c_members_backtrace_push('elements[{}]'.format(unique_i)):
encode_lines, decode_lines = self.format_type_inner(
type_.element_type,
checker.element_type)
if checker.minimum == checker.maximum:
first_encode_lines = first_decode_lines = [
'',
'for {} in 0..{} {{'.format(unique_i, checker.maximum)
]
else:
location = self.location_inner('', '.')
first_encode_lines = [
'encoder.append_non_negative_binary_integer(',
' (self.{}length - {}) as u64,'.format(location,
checker.minimum),
' {});'.format(type_.number_of_bits),
'',
'for {} in 0..self.{}length {{'.format(unique_i, location)
]
first_decode_lines = [
'self.{}length = '
'decoder.read_non_negative_binary_integer({});'.format(
location,
type_.number_of_bits),
'self.{}length += {};'.format(location, checker.minimum),
''
]
if not does_bits_match_range(type_.number_of_bits,
checker.minimum,
checker.maximum):
first_decode_lines += [
'if self.{}length > {} {{'.format(location, checker.maximum),
' decoder.abort(Error::BadLength);',
'',
' return;',
'}',
''
]
first_decode_lines += [
'for {} in 0..self.{}length {{'.format(unique_i, location)
]
encode_lines = first_encode_lines + indent_lines(encode_lines) + ['}', '']
decode_lines = first_decode_lines + indent_lines(decode_lines) + ['}', '']
return encode_lines, decode_lines
def format_type_inner(self, type_, checker):
if isinstance(type_, uper.Integer):
return self.format_integer_inner(type_, checker)
elif isinstance(type_, uper.Real):
return self.format_real_inner()
elif isinstance(type_, uper.Null):
return [], []
elif isinstance(type_, uper.Boolean):
return self.format_boolean_inner()
elif is_user_type(type_):
return self.format_user_type_inner()
elif isinstance(type_, uper.OctetString):
return self.format_octet_string_inner(type_, checker)
elif isinstance(type_, uper.Sequence):
return self.format_sequence_inner(type_, checker)
elif isinstance(type_, uper.Choice):
return self.format_choice_inner(type_, checker)
elif isinstance(type_, uper.SequenceOf):
return self.format_sequence_of_inner(type_, checker)
elif isinstance(type_, uper.Enumerated):
return self.format_enumerated_inner(type_)
else:
raise self.error(type_)
def generate_encoder(self, definitions):
functions = [
('encoder.init(', ENCODER_INIT),
('encoder.get_result(', ENCODER_GET_RESULT),
('encoder.abort(', ENCODER_ABORT),
('encoder.append_bit(', ENCODER_ALLOC),
('encoder.append_bit(', ENCODER_APPEND_BIT),
('encoder.append_bytes(', ENCODER_APPEND_BYTES),
('encoder.append_u8(', ENCODER_APPEND_U8),
('encoder.append_u16(', ENCODER_APPEND_U16),
('encoder.append_u32(', ENCODER_APPEND_U32),
('encoder.append_u64(', ENCODER_APPEND_U64),
('encoder.append_i8(', ENCODER_APPEND_I8),
('encoder.append_i16(', ENCODER_APPEND_I16),
('encoder.append_i32(', ENCODER_APPEND_I32),
('encoder.append_i64(', ENCODER_APPEND_I64),
('encoder.append_bool(', ENCODER_APPEND_BOOL),
(
'encoder.append_non_negative_binary_integer(',
ENCODER_APPEND_NON_NEGATIVE_BINARY_INTEGER
)
]
helpers = [
"impl<'a> Encoder<'a> {",
" fn new(dst: &'a mut [u8]) -> Encoder {",
' Encoder {',
' size: 8 * dst.len(),',
' buf: dst,',
' pos: 0,',
' error: None',
' }',
' }'
]
for pattern, definition in functions:
if pattern in definitions:
helpers.append(definition)
return helpers + ['}', '']
def generate_decoder(self, definitions):
functions = [
('decoder.init(', DECODER_INIT),
('decoder.get_result(', DECODER_GET_RESULT),
('decoder.abort(', DECODER_ABORT),
('decoder.read_bit(', DECODER_FREE),
('decoder.read_bit(', DECODER_READ_BIT),
('decoder.read_bytes(', DECODER_READ_BYTES),
('decoder.read_u8(', DECODER_READ_U8),
('decoder.read_u16(', DECODER_READ_U16),
('decoder.read_u32(', DECODER_READ_U32),
('decoder.read_u64(', DECODER_READ_U64),
('decoder.read_i8(', DECODER_READ_I8),
('decoder.read_i16(', DECODER_READ_I16),
('decoder.read_i32(', DECODER_READ_I32),
('decoder.read_i64(', DECODER_READ_I64),
('decoder.read_bool(', DECODER_READ_BOOL),
(
'decoder.read_non_negative_binary_integer(',
DECODER_READ_NON_NEGATIVE_BINARY_INTEGER
)
]
helpers = [
"impl<'a> Decoder<'a> {",
" fn new(src: &'a[u8]) -> Decoder {",
' Decoder {',
' buf: src,',
' size: 8 * src.len(),',
' pos: 0,',
' error: None',
' }',
' }'
]
for pattern, definition in functions:
if pattern in definitions:
helpers.append(definition)
return helpers + ['}']
def generate_helpers(self, definitions):
helpers = [ENCODER_AND_DECODER_STRUCTS]
helpers += self.generate_encoder(definitions)
helpers += self.generate_decoder(definitions)
return helpers + ['']
def generate(compiled):
return _Generator().generate(compiled)
asn1tools-0.169.0/asn1tools/source/rust/utils.py 0000664 0000000 0000000 00000044712 15245442746 0021571 0 ustar 00root root 0000000 0000000 import re
from ...errors import Error
TYPE_DECLARATION_FMT = '''\
/// Type {type_name} in module {module_name}.
{members}
'''
DEFINITION_FMT = '''
impl {module_name}{type_name} {{
pub fn encode(&mut self, mut dst: &mut [u8]) -> Result {{
let mut encoder = Encoder::new(&mut dst);
self.encode_inner(&mut encoder);
encoder.get_result()
}}
pub fn decode(&mut self, src: &[u8]) -> Result {{
let mut decoder = Decoder::new(&src);
self.decode_inner(&mut decoder);
decoder.get_result()
}}
fn encode_inner(&mut self, encoder: &mut Encoder) {{
{encode_body}\
}}
fn decode_inner(&mut self, decoder: &mut Decoder) {{
{decode_body}\
}}
}}
'''
ENCODER_AND_DECODER_STRUCTS = '''\
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Error {
BadChoice,
BadEnum,
BadLength,
OutOfData,
OutOfMemory
}
struct Encoder<'a> {
buf: &'a mut [u8],
size: usize,
pos: usize,
error: Option
}
struct Decoder<'a> {
buf: &'a[u8],
size: usize,
pos: usize,
error: Option
}
'''
ENCODER_ABORT = '''
fn abort(&mut self, error: Error) {
if self.error.is_none() {
self.error = Some(error);
}
}\
'''
DECODER_ABORT = '''
fn abort(&mut self, error: Error) {
if self.error.is_none() {
self.error = Some(error);
}
}\
'''
class _MembersBacktracesContext(object):
def __init__(self, backtraces, member_name):
self.backtraces = backtraces
self.member_name = member_name
def __enter__(self):
for backtrace in self.backtraces:
backtrace.append(self.member_name)
def __exit__(self, *args):
for backtrace in self.backtraces:
backtrace.pop()
class _UserType(object):
def __init__(self,
type_name,
module_name,
type_code,
used_user_types):
self.type_name = type_name
self.module_name = module_name
self.type_code = type_code
self.used_user_types = used_user_types
class Generator(object):
def __init__(self):
self.namespace = 'a'
self.asn1_members_backtrace = []
self.c_members_backtrace = []
self.module_name = None
self.type_name = None
self.helper_lines = []
self.base_variables = set()
self.used_suffixes_by_base_variables = {}
self.encode_variable_lines = []
self.decode_variable_lines = []
self.used_user_types = []
def reset_type(self):
self.helper_lines = []
self.base_variables = set()
self.used_suffixes_by_base_variables = {}
self.encode_variable_lines = []
self.decode_variable_lines = []
self.used_user_types = []
@property
def module_name_snake(self):
return camel_to_snake_case(self.module_name)
@property
def type_name_snake(self):
return camel_to_snake_case(self.type_name)
def type_length(self, minimum, maximum):
# Make sure it fits in 64 bits.
if minimum < -9223372036854775808:
raise self.error(
'{} does not fit in int64_t.'.format(minimum))
elif maximum > 18446744073709551615:
raise self.error(
'{} does not fit in uint64_t.'.format(maximum))
elif minimum < 0 and maximum > 9223372036854775807:
raise self.error(
'{} does not fit in int64_t.'.format(maximum))
# Calculate the number of bytes needed.
if minimum < -4294967296:
minimum_length = 64
elif minimum < -65536:
minimum_length = 32
elif minimum < -256:
minimum_length = 16
elif minimum < 0:
minimum_length = 8
else:
minimum_length = 0
if maximum > 4294967295:
maximum_length = 64
elif maximum > 65535:
maximum_length = 32
elif maximum > 255:
maximum_length = 16
elif maximum > 0:
maximum_length = 8
else:
maximum_length = 0
if minimum_length == maximum_length == 0:
length = 8
else:
length = max(minimum_length, maximum_length)
return length
def format_type_name(self, minimum, maximum):
length = self.type_length(minimum, maximum)
if minimum >= 0:
type_name = 'u{}'.format(length)
else:
type_name = 'i{}'.format(length)
return type_name
@property
def location(self):
location = '{}{}'.format(self.module_name,
self.type_name)
for member in self.asn1_members_backtrace:
location += make_camel_case(member)
return location
def location_inner(self, default='value', end=''):
if self.c_members_backtrace:
return '.'.join(self.c_members_backtrace) + end
else:
return default
def location_error(self):
location = '{}.{}'.format(self.module_name, self.type_name)
if self.asn1_members_backtrace:
location += '.{}'.format('.'.join(self.asn1_members_backtrace))
return location
def members_backtrace_push(self, member_name):
backtraces = [
self.asn1_members_backtrace,
self.c_members_backtrace
]
return _MembersBacktracesContext(backtraces, member_name)
def asn1_members_backtrace_push(self, member_name):
backtraces = [self.asn1_members_backtrace]
return _MembersBacktracesContext(backtraces, member_name)
def c_members_backtrace_push(self, member_name):
backtraces = [self.c_members_backtrace]
return _MembersBacktracesContext(backtraces, member_name)
def get_member_checker(self, checker, name):
for member in checker.members:
if member.name == name:
return member
raise Error('No member checker found for {}.'.format(name))
def add_unique_variable(self, name):
if name in self.base_variables:
try:
suffix = self.used_suffixes_by_base_variables[name]
suffix += 1
except KeyError:
suffix = 2
self.used_suffixes_by_base_variables[name] = suffix
unique_name = '{}_{}'.format(name, suffix)
else:
self.base_variables.add(name)
unique_name = name
return unique_name
def error(self, message):
return Error('{}: {}'.format(self.location_error(), message))
def format_integer(self, checker):
if not checker.has_lower_bound():
raise self.error('INTEGER has no minimum value.')
if not checker.has_upper_bound():
raise self.error('INTEGER has no maximum value.')
type_name = self.format_type_name(checker.minimum, checker.maximum)
return [type_name]
def format_boolean(self):
return ['bool']
def format_octet_string(self, checker):
if not checker.has_upper_bound():
raise self.error('OCTET STRING has no maximum length.')
if checker.minimum == checker.maximum:
lines = []
elif checker.maximum < 256:
lines = [' let length: u8;']
else:
lines = [' let length: u32;']
return [
'#[derive(Debug, Default, PartialEq, Copy, Clone)]',
'pub struct {} {{'.format(self.location)
] + lines + [
' pub buf: [u8; {}]'.format(checker.maximum),
'}'
]
def format_sequence(self, type_, checker):
helper_lines = []
lines = []
for member in type_.root_members:
member_checker = self.get_member_checker(checker, member.name)
if member.optional:
lines += ['pub is_{}_present: bool,'.format(member.name)]
with self.members_backtrace_push(member.name):
member_lines = self.format_type(member, member_checker)
member_location = self.location
if not member_lines:
continue
if is_inline_member_lines(member_lines):
member_lines[-1] = 'pub {}: {},'.format(member.name,
member_lines[-1])
else:
helper_lines += member_lines + ['']
member_lines = ['pub {}: {},'.format(member.name,
member_location)]
lines += member_lines
if lines:
lines[-1] = lines[-1].strip(',')
return helper_lines + [
'#[derive(Debug, Default, PartialEq, Copy, Clone)]',
'pub struct {} {{'.format(self.location)
] + indent_lines(lines) + [
'}'
]
def format_sequence_of(self, type_, checker):
if not checker.is_bound():
raise self.error('SEQUENCE OF has no maximum length.')
with self.asn1_members_backtrace_push('elem'):
lines = self.format_type(type_.element_type,
checker.element_type)
if lines:
lines[-1] += ' elements[{}];'.format(checker.maximum)
if checker.minimum == checker.maximum:
length_lines = []
elif checker.maximum < 256:
length_lines = ['let length: u8;']
else:
length_lines = ['let length: u32;']
return ['struct {'] + indent_lines(length_lines + lines) + ['}']
def format_enumerated(self, type_):
lines = [
'#[derive(Debug, PartialEq, Copy, Clone)]',
'pub enum {} {{'.format(self.location)
] + [
' {},'.format(make_camel_case(value))
for value in self.get_enumerated_values(type_)
] + [
'}',
'',
'impl Default for {} {{'.format(self.location),
' fn default() -> Self {',
' {}::{}'.format(self.location,
self.get_enumerated_values(type_)[0].upper()),
' }',
'}'
]
return lines
def format_choice(self, type_, checker):
helper_lines = []
lines = []
for member in self.get_choice_members(type_):
member_checker = self.get_member_checker(checker,
member.name)
with self.members_backtrace_push(member.name):
member_lines = self.format_type(member, member_checker)
member_location = self.location
if not member_lines:
continue
if is_inline_member_lines(member_lines):
member_lines[-1] = '{}({}),'.format(make_camel_case(member.name),
member_lines[-1])
else:
helper_lines += member_lines + ['']
member_lines = ['pub {}: {},'.format(member.name,
member_location)]
lines += member_lines
if lines:
lines[-1] = lines[-1].strip(',')
return helper_lines + [
'#[derive(Debug, PartialEq, Copy, Clone)]',
'pub enum {} {{'.format(self.location)
] + indent_lines(lines) + [
'}'
]
def format_user_type(self, type_name, module_name):
self.used_user_types.append((type_name, module_name))
return ['{}{}'.format(module_name, type_name)]
def format_sequence_inner_member(self,
member,
checker,
default_condition_by_member_name):
member_checker = self.get_member_checker(checker, member.name)
with self.members_backtrace_push(member.name):
encode_lines, decode_lines = self.format_type_inner(
member,
member_checker)
location = self.location_inner('', '.')
if member.optional:
is_present = '{}is_{}_present'.format(location, member.name)
encode_lines = [
'',
'if src.{} {{'.format(is_present)
] + indent_lines(encode_lines) + [
'}',
''
]
decode_lines = [
'',
'if dst.{} {{'.format(is_present)
] + indent_lines(decode_lines) + [
'}',
''
]
elif member.default is not None:
name = '{}{}'.format(location, member.name)
encode_lines = [
'',
'if src.{} != {} {{'.format(name, member.default)
] + indent_lines(encode_lines) + [
'}',
''
]
decode_lines = [
'',
'if {} {{'.format(default_condition_by_member_name[member.name])
] + indent_lines(decode_lines) + [
'} else {',
' dst.{} = {};'.format(name, member.default),
'}',
''
]
return encode_lines, decode_lines
def generate_type_declaration(self, compiled_type):
type_ = compiled_type.type
checker = compiled_type.constraints_checker.type
lines = self.generate_type_declaration_process(type_, checker)
if not lines:
lines = ['dummy: u8;']
if self.helper_lines:
self.helper_lines.append('')
return TYPE_DECLARATION_FMT.format(module_name=self.module_name,
type_name=self.type_name,
members='\n'.join(lines))
def generate_definition(self, compiled_type):
encode_lines, decode_lines = self.generate_definition_inner_process(
compiled_type.type,
compiled_type.constraints_checker.type)
if self.encode_variable_lines:
encode_lines = self.encode_variable_lines + [''] + encode_lines
if self.decode_variable_lines:
decode_lines = self.decode_variable_lines + [''] + decode_lines
encode_lines = indent_lines(indent_lines(encode_lines)) + ['']
decode_lines = indent_lines(indent_lines(decode_lines)) + ['']
return DEFINITION_FMT.format(module_name=self.module_name,
type_name=self.type_name,
encode_body='\n'.join(encode_lines),
decode_body='\n'.join(decode_lines))
def generate(self, compiled):
user_types = []
for module_name, module in sorted(compiled.modules.items()):
self.module_name = module_name
for type_name, compiled_type in sorted(module.items()):
self.type_name = type_name
self.reset_type()
type_declaration = self.generate_type_declaration(compiled_type)
definition = self.generate_definition(compiled_type)
user_type = _UserType(type_name,
module_name,
type_declaration + definition,
self.used_user_types)
user_types.append(user_type)
user_types = sort_user_types_by_used_user_types(user_types)
types_code = []
for user_type in user_types:
types_code.append(user_type.type_code)
types_code = '\n'.join(types_code)
helpers = '\n'.join(self.generate_helpers(types_code))
return helpers, types_code
def format_type(self, type_, checker):
raise NotImplementedError('To be implemented by subclasses.')
def format_type_inner(self, type_, checker):
raise NotImplementedError('To be implemented by subclasses.')
def get_enumerated_values(self, type_):
raise NotImplementedError('To be implemented by subclasses.')
def get_choice_members(self, type_):
raise NotImplementedError('To be implemented by subclasses.')
def generate_type_declaration_process(self, type_, checker):
raise NotImplementedError('To be implemented by subclasses.')
def generate_definition_inner_process(self, type_, checker):
raise NotImplementedError('To be implemented by subclasses.')
def generate_helpers(self, definitions):
raise NotImplementedError('To be implemented by subclasses.')
def canonical(value):
"""Replace anything but 'a-z', 'A-Z' and '0-9' with '_'.
"""
return re.sub(r'[^a-zA-Z0-9]', '_', value)
def camel_to_snake_case(value):
value = re.sub(r'(.)([A-Z][a-z]+)', r'\1_\2', value)
value = re.sub(r'(_+)', '_', value)
value = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', value).lower()
value = canonical(value)
return value
def make_camel_case(value):
return value[0].upper() + value[1:]
def join_lines(lines, suffix):
return[line + suffix for line in lines[:-1]] + lines[-1:]
def is_user_type(type_):
return type_.module_name is not None
def strip_blank_lines(lines):
try:
while lines[0] == '':
del lines[0]
while lines[-1] == '':
del lines[-1]
except IndexError:
pass
stripped = []
for line in lines:
if line == '' and stripped[-1] == '':
continue
stripped.append(line)
return stripped
def indent_lines(lines, width=4):
indented_lines = []
for line in lines:
if line:
indented_line = width * ' ' + line
else:
indented_line = line
indented_lines.append(indented_line)
return strip_blank_lines(indented_lines)
def dedent_lines(lines, width=4):
return [line[width:] for line in lines]
def sort_user_types_by_used_user_types(user_types):
reversed_sorted_user_types = []
for user_type in user_types:
user_type_name_tuple = (user_type.type_name, user_type.module_name)
# Insert first in the reversed list if there are no types
# using this type.
insert_index = 0
for i, reversed_sorted_user_type in enumerate(reversed_sorted_user_types, 1):
if user_type_name_tuple in reversed_sorted_user_type.used_user_types:
if i > insert_index:
insert_index = i
reversed_sorted_user_types.insert(insert_index, user_type)
return reversed(reversed_sorted_user_types)
def is_inline_member_lines(member_lines):
return len(member_lines) == 1
asn1tools-0.169.0/asn1tools/version.py 0000664 0000000 0000000 00000000030 15245442746 0017602 0 ustar 00root root 0000000 0000000 __version__ = '0.169.0'
asn1tools-0.169.0/docs/ 0000775 0000000 0000000 00000000000 15245442746 0014557 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/docs/Makefile 0000664 0000000 0000000 00000016375 15245442746 0016233 0 ustar 00root root 0000000 0000000 # Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
help:
@echo "Please use \`make ' where is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/asn1tools.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/asn1tools.qhc"
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/asn1tools"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/asn1tools"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
asn1tools-0.169.0/docs/conf.py 0000664 0000000 0000000 00000022167 15245442746 0016066 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
#
# asn1tools documentation build configuration file, created by
# sphinx-quickstart on Sat Apr 25 11:54:09 2015.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
import shlex
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('..'))
import asn1tools
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.viewcode',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'asn1tools'
copyright = u'2017-2019, Erik Moqvist'
author = u'Erik Moqvist'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = asn1tools.__version__
# The full version, including alpha/beta/rc tags.
release = asn1tools.__version__
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# " v documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
#html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
#html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'asn1toolsdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'asn1tools.tex', u'asn1tools Documentation',
u'Erik Moqvist', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'asn1tools', u'Asn1tools Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'asn1tools', u'ASN.1 tools documentation.',
author, 'asn1tools', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
autodoc_member_order = 'bysource'
asn1tools-0.169.0/docs/index.rst 0000664 0000000 0000000 00000014065 15245442746 0016426 0 ustar 00root root 0000000 0000000 .. asn1tools documentation master file, created by
sphinx-quickstart on Sat Apr 25 11:54:09 2015.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
.. toctree::
:maxdepth: 2
ASN.1 tools
===========
.. include:: ../README.rst
Basic Usage
===========
.. autofunction:: asn1tools.compile_files
.. autoclass:: asn1tools.compiler.Specification
:members:
Types
=====
ASN.1 types are mapped to Python 3 types as shown in the table
below. In Python 2, INTEGER may be ``long`` and all string types are
``unicode``.
+-------------------+------------------------+---------------------------------------+
| ASN.1 type | Python type | Example |
+===================+========================+=======================================+
| BOOLEAN | ``bool`` | ``True`` |
+-------------------+------------------------+---------------------------------------+
| INTEGER | ``int`` | ``87`` |
+-------------------+------------------------+---------------------------------------+
| REAL | ``float`` | ``33.12`` |
+-------------------+------------------------+---------------------------------------+
| NULL | -- | ``None`` |
+-------------------+------------------------+---------------------------------------+
| BIT STRING | ``tuple(bytes, int)`` | ``(b'\x50', 4)`` |
+-------------------+------------------------+---------------------------------------+
| OCTET STRING | ``bytes`` | ``b'\x44\x1e\xff'`` |
+-------------------+------------------------+---------------------------------------+
| OBJECT IDENTIFIER | ``str`` | ``'1.33.2'`` |
+-------------------+------------------------+---------------------------------------+
| ENUMERATED | ``str`` or ``int`` (1) | ``'one'`` or ``1`` |
+-------------------+------------------------+---------------------------------------+
| SEQUENCE | ``dict`` | ``{'a': 52, 'b': 1}`` |
+-------------------+------------------------+---------------------------------------+
| SEQUENCE OF | ``list`` | ``[1, 3]`` |
+-------------------+------------------------+---------------------------------------+
| SET | ``dict`` | ``{'foo': 'bar'}`` |
+-------------------+------------------------+---------------------------------------+
| SET OF | ``list`` | ``[3, 0, 7]`` |
+-------------------+------------------------+---------------------------------------+
| CHOICE | ``tuple(str, object)`` | ``('a', 5)`` |
+-------------------+------------------------+---------------------------------------+
| UTF8String | ``str`` | ``'hello'`` |
+-------------------+------------------------+---------------------------------------+
| NumericString | ``str`` | ``'234359'`` |
+-------------------+------------------------+---------------------------------------+
| PrintableString | ``str`` | ``'goo'`` |
+-------------------+------------------------+---------------------------------------+
| IA5String | ``str`` | ``'name'`` |
+-------------------+------------------------+---------------------------------------+
| VisibleString | ``str`` | ``'gle'`` |
+-------------------+------------------------+---------------------------------------+
| GeneralString | ``str`` | ``'abc'`` |
+-------------------+------------------------+---------------------------------------+
| BMPString | ``str`` | ``'ko'`` |
+-------------------+------------------------+---------------------------------------+
| GraphicString | ``str`` | ``'a b'`` |
+-------------------+------------------------+---------------------------------------+
| TeletexString | ``str`` | ``'ßø'`` |
+-------------------+------------------------+---------------------------------------+
| UniversalString | ``str`` | ``'åäö'`` |
+-------------------+------------------------+---------------------------------------+
| UTCTime | ``datetime.datetime`` | ``datetime(2018, 6, 11, 11, 4, 59)`` |
+-------------------+------------------------+---------------------------------------+
| GeneralizedTime | ``datetime.datetime`` | ``datetime(2018, 1, 31, 5, 0, 47)`` |
+-------------------+------------------------+---------------------------------------+
| DATE | ``datetime.date`` | ``date(1985, 4, 12)`` |
+-------------------+------------------------+---------------------------------------+
| TIME-OF-DAY | ``datetime.time`` | ``time(15, 27, 46)`` |
+-------------------+------------------------+---------------------------------------+
| DATE-TIME | ``datetime.datetime`` | ``datetime(1985, 4, 12, 15, 27, 30)`` |
+-------------------+------------------------+---------------------------------------+
| ObjectDescriptor | -- | -- |
+-------------------+------------------------+---------------------------------------+
(1) Compile with ``numeric_enums=True`` for numeric enumeration values
instead of strings.
Advanced Usage
==============
.. autofunction:: asn1tools.compile_string
.. autofunction:: asn1tools.compile_dict
.. autofunction:: asn1tools.parse_files
.. autofunction:: asn1tools.parse_string
asn1tools-0.169.0/docs/make.bat 0000664 0000000 0000000 00000016122 15245442746 0016166 0 ustar 00root root 0000000 0000000 @ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^` where ^ is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
echo. coverage to run coverage check of the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
REM Check if sphinx-build is available and fallback to Python version if any
%SPHINXBUILD% 2> nul
if errorlevel 9009 goto sphinx_python
goto sphinx_ok
:sphinx_python
set SPHINXBUILD=python -m sphinx.__init__
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
:sphinx_ok
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\asn1tools.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\asn1tools.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %~dp0
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %~dp0
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "coverage" (
%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
if errorlevel 1 exit /b 1
echo.
echo.Testing of coverage in the sources finished, look at the ^
results in %BUILDDIR%/coverage/python.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
:end
asn1tools-0.169.0/examples/ 0000775 0000000 0000000 00000000000 15245442746 0015445 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/examples/README.rst 0000664 0000000 0000000 00000000104 15245442746 0017127 0 ustar 00root root 0000000 0000000 Examples
========
This folder contains executable example scripts.
asn1tools-0.169.0/examples/benchmarks/ 0000775 0000000 0000000 00000000000 15245442746 0017562 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/examples/benchmarks/c_source/ 0000775 0000000 0000000 00000000000 15245442746 0021364 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/examples/benchmarks/c_source/Makefile 0000664 0000000 0000000 00000000101 15245442746 0023014 0 ustar 00root root 0000000 0000000 all:
$(MAKE) -C asn1tools
$(MAKE) -C asn1scc
$(MAKE) -C asn1c
asn1tools-0.169.0/examples/benchmarks/c_source/README.rst 0000664 0000000 0000000 00000023676 15245442746 0023071 0 ustar 00root root 0000000 0000000 About
=====
Benchmark of generated C source code from asn1c and asn1tools.
Executable size
---------------
The `asn1c` executable is a lot bigger than `asn1tools` and `asn1scc`
because it contains encode and decode functions for all codecs, not
only uper as for `asn1tools` and `asn1scc`. There is no `asn1c` option
to only generate uper code. `asn1c` also supports more ASN.1 construts
and uses dynamic memory.
asn1tools:
.. code-block::
text data bss dec hex filename
5553 560 8 6121 17e9 main
asn1scc:
.. code-block::
text data bss dec hex filename
12073 560 8 12641 3161 main
asn1c:
.. code-block::
text data bss dec hex filename
63733 4904 80 68717 10c6d main
Execution time
--------------
Encoding and decoding the PDU type 1,000,000 times for each tool and
optimization combination.
+-----------+--------------+--------------------+
| Tool | Optimization | Exexution time [s] |
+===========+==============+====================+
| asn1tools | -O3 | 1.229 |
+-----------+--------------+--------------------+
| asn1tools | -Os | 2.987 |
+-----------+--------------+--------------------+
| asn1scc | -O3 | 4.023 |
+-----------+--------------+--------------------+
| asn1scc | -Os | 6.166 |
+-----------+--------------+--------------------+
| asn1c | -O3 | 10.902 |
+-----------+--------------+--------------------+
| asn1c | -Os | 12.569 |
+-----------+--------------+--------------------+
Source code statistics
----------------------
`asn1tools` has the fewest lines of code, only 832. `asn1scc` has 3549
and `asn1c` 10159.
The statistics was created with `cloc`.
asn1tools:
.. code-block::
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 1 178 28 670
C/C++ Header 1 36 196 162
-------------------------------------------------------------------------------
SUM: 2 214 224 832
-------------------------------------------------------------------------------
asn1scc:
.. code-block::
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 4 697 126 3020
C/C++ Header 2 176 28 529
-------------------------------------------------------------------------------
SUM: 6 873 154 3549
-------------------------------------------------------------------------------
asn1c:
.. code-block::
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 34 1421 1822 8834
C/C++ Header 38 398 762 1325
-------------------------------------------------------------------------------
SUM: 72 1819 2584 10159
-------------------------------------------------------------------------------
Runtime memory usage
--------------------
The runtime memory usage was captured with Valgrind Massif on a 64
bits Ubuntu 16 machine.
asn1tools:
.. code-block::
--------------------------------------------------------------------------------
n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B)
--------------------------------------------------------------------------------
52 209,480 1,192 0 0 1,192
53 211,936 1,648 0 0 1,648
54 214,464 1,744 0 0 1,744
55 216,904 1,192 0 0 1,192
56 219,328 320 0 0 320
57 221,872 800 0 0 800
58 224,296 936 0 0 936
59 226,720 912 0 0 912
60 229,144 968 0 0 968
61 231,568 912 0 0 912
62 234,088 232 0 0 232
63 236,512 736 0 0 736
64 238,936 520 0 0 520
65 241,376 432 0 0 432
66 243,808 448 0 0 448
67 246,288 480 0 0 480
68 248,752 416 0 0 416
69 251,176 408 0 0 408
asn1scc:
.. code-block::
--------------------------------------------------------------------------------
n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B)
--------------------------------------------------------------------------------
52 209,480 1,192 0 0 1,192
53 211,936 1,648 0 0 1,648
54 214,464 1,744 0 0 1,744
55 216,904 1,192 0 0 1,192
56 219,328 320 0 0 320
57 222,240 1,168 0 0 1,168
58 224,664 1,224 0 0 1,224
59 227,088 1,440 0 0 1,440
60 229,512 1,672 0 0 1,672
61 232,120 248 0 0 248
62 234,544 720 0 0 720
63 236,968 536 0 0 536
64 239,424 432 0 0 432
65 241,856 448 0 0 448
66 244,336 480 0 0 480
67 246,800 416 0 0 416
68 249,224 408 0 0 408
asn1c:
.. code-block::
--------------------------------------------------------------------------------
n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B)
--------------------------------------------------------------------------------
59 226,712 1,192 0 0 1,192
60 229,168 1,648 0 0 1,648
61 231,696 1,744 0 0 1,744
62 234,128 256 0 0 256
63 236,552 280 0 0 280
64 238,976 1,056 596 92 368
65 241,400 1,464 903 185 376
66 243,824 1,888 920 208 760
67 246,264 2,632 920 208 1,504
68 248,688 2,784 920 208 1,656
69 251,112 2,584 920 208 1,456
70 253,600 2,000 920 208 872
71 256,048 1,584 743 121 720
72 258,608 400 0 0 400
73 261,080 1,368 262 50 1,056
74 263,560 1,832 434 54 1,344
75 265,984 2,224 524 92 1,608
76 268,408 2,232 536 104 1,592
77 270,880 2,464 579 109 1,776
78 273,304 2,568 643 181 1,744
79 275,792 2,704 689 231 1,784
80 278,232 1,944 719 217 1,008
81 280,680 2,536 920 256 1,360
82 283,104 1,712 920 256 536
83 285,632 1,072 481 63 528
84 288,056 520 0 0 520
85 290,544 1,600 0 0 1,600
86 292,968 488 0 0 488
87 295,392 480 0 0 480
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/ 0000775 0000000 0000000 00000000000 15245442746 0022371 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/Makefile 0000664 0000000 0000000 00000001565 15245442746 0024040 0 ustar 00root root 0000000 0000000 ASN1C ?= ../asn1c-0.9.28/asn1c/asn1c
ASN1C_FLAGS = -fcompound-names -fincludes-quoted -gen-PER
all:
gcc $(CFLAGS) $(OPT_SIZE) generated/*.c main.c -o main
size main
readelf -s -W main | sort -k3 -n
valgrind $(MASSIF_FLAGS) --massif-out-file=main.massif ./main 1
ms_print main.massif
time ./main $(ENCODE_DECODE_ITERATIONS)
gcc $(CFLAGS) $(OPT_SPEED) generated/*.c main.c -o main
time ./main $(ENCODE_DECODE_ITERATIONS)
generate: asn1c-0.9.28
rm -rf generated
mkdir -p generated
cd generated && \
$(ASN1C) $(ASN1C_FLAGS) ../../my_protocol.asn && \
rm Makefile.am.sample converter-sample.c
v0.9.28.tar.gz:
wget https://github.com/vlm/asn1c/archive/v0.9.28.tar.gz
asn1c-0.9.28: v0.9.28.tar.gz
rm -rf asn1c-0.9.28
tar xf v0.9.28.tar.gz
cd asn1c-0.9.28 && \
test -f configure || autoreconf -iv && \
./configure && \
$(MAKE)
include ../common.mk
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/ 0000775 0000000 0000000 00000000000 15245442746 0024327 5 ustar 00root root 0000000 0000000 asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/A.c 0000664 0000000 0000000 00000002713 15245442746 0024656 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#include "A.h"
static asn_per_constraints_t asn_PER_type_A_constr_1 GCC_NOTUSED = {
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
{ APC_CONSTRAINED, 2, 2, 2, 5 } /* (SIZE(2..5)) */,
0, 0 /* No PER value map */
};
static asn_TYPE_member_t asn_MBR_A_1[] = {
{ ATF_POINTER, 0, 0,
-1 /* Ambiguous tag (CHOICE?) */,
0,
&asn_DEF_B,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
""
},
};
static const ber_tlv_tag_t asn_DEF_A_tags_1[] = {
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
};
static asn_SET_OF_specifics_t asn_SPC_A_specs_1 = {
sizeof(struct A),
offsetof(struct A, _asn_ctx),
2, /* XER encoding is XMLValueList */
};
asn_TYPE_descriptor_t asn_DEF_A = {
"A",
"A",
SEQUENCE_OF_free,
SEQUENCE_OF_print,
SEQUENCE_OF_constraint,
SEQUENCE_OF_decode_ber,
SEQUENCE_OF_encode_der,
SEQUENCE_OF_decode_xer,
SEQUENCE_OF_encode_xer,
SEQUENCE_OF_decode_uper,
SEQUENCE_OF_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_A_tags_1,
sizeof(asn_DEF_A_tags_1)
/sizeof(asn_DEF_A_tags_1[0]), /* 1 */
asn_DEF_A_tags_1, /* Same as above */
sizeof(asn_DEF_A_tags_1)
/sizeof(asn_DEF_A_tags_1[0]), /* 1 */
&asn_PER_type_A_constr_1,
asn_MBR_A_1,
1, /* Single element */
&asn_SPC_A_specs_1 /* Additional specs */
};
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/A.h 0000664 0000000 0000000 00000001367 15245442746 0024667 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#ifndef _A_H_
#define _A_H_
#include "asn_application.h"
/* Including external dependencies */
#include "asn_SEQUENCE_OF.h"
#include "constr_SEQUENCE_OF.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Forward declarations */
struct B;
/* A */
typedef struct A {
A_SEQUENCE_OF(struct B) list;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} A_t;
/* Implementation */
extern asn_TYPE_descriptor_t asn_DEF_A;
#ifdef __cplusplus
}
#endif
/* Referred external types */
#include "B.h"
#endif /* _A_H_ */
#include "asn_internal.h"
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/B.c 0000664 0000000 0000000 00000003523 15245442746 0024657 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#include "B.h"
static asn_per_constraints_t asn_PER_type_B_constr_1 GCC_NOTUSED = {
{ APC_CONSTRAINED, 1, 1, 0, 1 } /* (0..1) */,
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
0, 0 /* No PER value map */
};
static asn_TYPE_member_t asn_MBR_B_1[] = {
{ ATF_NOFLAGS, 0, offsetof(struct B, choice.a),
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
-1, /* IMPLICIT tag at current level */
&asn_DEF_C,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"a"
},
{ ATF_NOFLAGS, 0, offsetof(struct B, choice.b),
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
-1, /* IMPLICIT tag at current level */
&asn_DEF_D,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"b"
},
};
static const asn_TYPE_tag2member_t asn_MAP_B_tag2el_1[] = {
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* a */
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* b */
};
static asn_CHOICE_specifics_t asn_SPC_B_specs_1 = {
sizeof(struct B),
offsetof(struct B, _asn_ctx),
offsetof(struct B, present),
sizeof(((struct B *)0)->present),
asn_MAP_B_tag2el_1,
2, /* Count of tags in the map */
0,
-1 /* Extensions start */
};
asn_TYPE_descriptor_t asn_DEF_B = {
"B",
"B",
CHOICE_free,
CHOICE_print,
CHOICE_constraint,
CHOICE_decode_ber,
CHOICE_encode_der,
CHOICE_decode_xer,
CHOICE_encode_xer,
CHOICE_decode_uper,
CHOICE_encode_uper,
CHOICE_outmost_tag,
0, /* No effective tags (pointer) */
0, /* No effective tags (count) */
0, /* No tags (pointer) */
0, /* No tags (count) */
&asn_PER_type_B_constr_1,
asn_MBR_B_1,
2, /* Elements count */
&asn_SPC_B_specs_1 /* Additional specs */
};
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/B.h 0000664 0000000 0000000 00000001447 15245442746 0024667 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#ifndef _B_H_
#define _B_H_
#include "asn_application.h"
/* Including external dependencies */
#include "C.h"
#include "D.h"
#include "constr_CHOICE.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Dependencies */
typedef enum B_PR {
B_PR_NOTHING, /* No components present */
B_PR_a,
B_PR_b
} B_PR;
/* B */
typedef struct B {
B_PR present;
union B_u {
C_t a;
D_t b;
} choice;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} B_t;
/* Implementation */
extern asn_TYPE_descriptor_t asn_DEF_B;
#ifdef __cplusplus
}
#endif
#endif /* _B_H_ */
#include "asn_internal.h"
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/BIT_STRING.c 0000664 0000000 0000000 00000010740 15245442746 0026201 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include
/*
* BIT STRING basic type description.
*/
static const ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
};
static asn_OCTET_STRING_specifics_t asn_DEF_BIT_STRING_specs = {
sizeof(BIT_STRING_t),
offsetof(BIT_STRING_t, _asn_ctx),
ASN_OSUBV_BIT
};
asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
"BIT STRING",
"BIT_STRING",
OCTET_STRING_free, /* Implemented in terms of OCTET STRING */
BIT_STRING_print,
BIT_STRING_constraint,
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
OCTET_STRING_decode_xer_binary,
BIT_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Unaligned PER decoder */
OCTET_STRING_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BIT_STRING_tags,
sizeof(asn_DEF_BIT_STRING_tags)
/ sizeof(asn_DEF_BIT_STRING_tags[0]),
asn_DEF_BIT_STRING_tags, /* Same as above */
sizeof(asn_DEF_BIT_STRING_tags)
/ sizeof(asn_DEF_BIT_STRING_tags[0]),
0, /* No PER visible constraints */
0, 0, /* No members */
&asn_DEF_BIT_STRING_specs
};
/*
* BIT STRING generic constraint.
*/
int
BIT_STRING_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
if(st && st->buf) {
if((st->size == 0 && st->bits_unused)
|| st->bits_unused < 0 || st->bits_unused > 7) {
ASN__CTFAIL(app_key, td, sptr,
"%s: invalid padding byte (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
} else {
ASN__CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
return 0;
}
static char *_bit_pattern[16] = {
"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
};
asn_enc_rval_t
BIT_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_enc_rval_t er;
char scratch[128];
char *p = scratch;
char *scend = scratch + (sizeof(scratch) - 10);
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
int xcan = (flags & XER_F_CANONICAL);
uint8_t *buf;
uint8_t *end;
if(!st || !st->buf)
ASN__ENCODE_FAILED;
er.encoded = 0;
buf = st->buf;
end = buf + st->size - 1; /* Last byte is special */
/*
* Binary dump
*/
for(; buf < end; buf++) {
int v = *buf;
int nline = xcan?0:(((buf - st->buf) % 8) == 0);
if(p >= scend || nline) {
er.encoded += p - scratch;
ASN__CALLBACK(scratch, p - scratch);
p = scratch;
if(nline) ASN__TEXT_INDENT(1, ilevel);
}
memcpy(p + 0, _bit_pattern[v >> 4], 4);
memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
p += 8;
}
if(!xcan && ((buf - st->buf) % 8) == 0)
ASN__TEXT_INDENT(1, ilevel);
er.encoded += p - scratch;
ASN__CALLBACK(scratch, p - scratch);
p = scratch;
if(buf == end) {
int v = *buf;
int ubits = st->bits_unused;
int i;
for(i = 7; i >= ubits; i--)
*p++ = (v & (1 << i)) ? 0x31 : 0x30;
er.encoded += p - scratch;
ASN__CALLBACK(scratch, p - scratch);
}
if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
ASN__ENCODED_OK(er);
cb_failed:
ASN__ENCODE_FAILED;
}
/*
* BIT STRING specific contents printer.
*/
int
BIT_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
const char * const h2c = "0123456789ABCDEF";
char scratch[64];
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
uint8_t *buf;
uint8_t *end;
char *p = scratch;
(void)td; /* Unused argument */
if(!st || !st->buf)
return (cb("", 8, app_key) < 0) ? -1 : 0;
ilevel++;
buf = st->buf;
end = buf + st->size;
/*
* Hexadecimal dump.
*/
for(; buf < end; buf++) {
if((buf - st->buf) % 16 == 0 && (st->size > 16)
&& buf != st->buf) {
_i_INDENT(1);
/* Dump the string */
if(cb(scratch, p - scratch, app_key) < 0) return -1;
p = scratch;
}
*p++ = h2c[*buf >> 4];
*p++ = h2c[*buf & 0x0F];
*p++ = 0x20;
}
if(p > scratch) {
p--; /* Eat the tailing space */
if((st->size > 16)) {
_i_INDENT(1);
}
/* Dump the incomplete 16-bytes row */
if(cb(scratch, p - scratch, app_key) < 0)
return -1;
}
return 0;
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/BIT_STRING.h 0000664 0000000 0000000 00000001470 15245442746 0026206 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _BIT_STRING_H_
#define _BIT_STRING_H_
#include /* Some help from OCTET STRING */
#ifdef __cplusplus
extern "C" {
#endif
typedef struct BIT_STRING_s {
uint8_t *buf; /* BIT STRING body */
int size; /* Size of the above buffer */
int bits_unused;/* Unused trailing bits in the last octet (0..7) */
asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */
} BIT_STRING_t;
extern asn_TYPE_descriptor_t asn_DEF_BIT_STRING;
asn_struct_print_f BIT_STRING_print; /* Human-readable output */
asn_constr_check_f BIT_STRING_constraint;
xer_type_encoder_f BIT_STRING_encode_xer;
#ifdef __cplusplus
}
#endif
#endif /* _BIT_STRING_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/BOOLEAN.c 0000664 0000000 0000000 00000014151 15245442746 0025554 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2005 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include
/*
* BOOLEAN basic type description.
*/
static const ber_tlv_tag_t asn_DEF_BOOLEAN_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (1 << 2))
};
asn_TYPE_descriptor_t asn_DEF_BOOLEAN = {
"BOOLEAN",
"BOOLEAN",
BOOLEAN_free,
BOOLEAN_print,
asn_generic_no_constraint,
BOOLEAN_decode_ber,
BOOLEAN_encode_der,
BOOLEAN_decode_xer,
BOOLEAN_encode_xer,
BOOLEAN_decode_uper, /* Unaligned PER decoder */
BOOLEAN_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BOOLEAN_tags,
sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
asn_DEF_BOOLEAN_tags, /* Same as above */
sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
0, /* No PER visible constraints */
0, 0, /* No members */
0 /* No specifics */
};
/*
* Decode BOOLEAN type.
*/
asn_dec_rval_t
BOOLEAN_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td,
void **bool_value, const void *buf_ptr, size_t size,
int tag_mode) {
BOOLEAN_t *st = (BOOLEAN_t *)*bool_value;
asn_dec_rval_t rval;
ber_tlv_len_t length;
ber_tlv_len_t lidx;
if(st == NULL) {
st = (BOOLEAN_t *)(*bool_value = CALLOC(1, sizeof(*st)));
if(st == NULL) {
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
}
}
ASN_DEBUG("Decoding %s as BOOLEAN (tm=%d)",
td->name, tag_mode);
/*
* Check tags.
*/
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
tag_mode, 0, &length, 0);
if(rval.code != RC_OK)
return rval;
ASN_DEBUG("Boolean length is %d bytes", (int)length);
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
size -= rval.consumed;
if(length > (ber_tlv_len_t)size) {
rval.code = RC_WMORE;
rval.consumed = 0;
return rval;
}
/*
* Compute boolean value.
*/
for(*st = 0, lidx = 0;
(lidx < length) && *st == 0; lidx++) {
/*
* Very simple approach: read bytes until the end or
* value is already TRUE.
* BOOLEAN is not supposed to contain meaningful data anyway.
*/
*st |= ((const uint8_t *)buf_ptr)[lidx];
}
rval.code = RC_OK;
rval.consumed += length;
ASN_DEBUG("Took %ld/%ld bytes to encode %s, value=%d",
(long)rval.consumed, (long)length,
td->name, *st);
return rval;
}
asn_enc_rval_t
BOOLEAN_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_enc_rval_t erval;
BOOLEAN_t *st = (BOOLEAN_t *)sptr;
erval.encoded = der_write_tags(td, 1, tag_mode, 0, tag, cb, app_key);
if(erval.encoded == -1) {
erval.failed_type = td;
erval.structure_ptr = sptr;
return erval;
}
if(cb) {
uint8_t bool_value;
bool_value = *st ? 0xff : 0; /* 0xff mandated by DER */
if(cb(&bool_value, 1, app_key) < 0) {
erval.encoded = -1;
erval.failed_type = td;
erval.structure_ptr = sptr;
return erval;
}
}
erval.encoded += 1;
ASN__ENCODED_OK(erval);
}
/*
* Decode the chunk of XML text encoding INTEGER.
*/
static enum xer_pbd_rval
BOOLEAN__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
BOOLEAN_t *st = (BOOLEAN_t *)sptr;
const char *p = (const char *)chunk_buf;
(void)td;
if(chunk_size && p[0] == 0x3c /* '<' */) {
switch(xer_check_tag(chunk_buf, chunk_size, "false")) {
case XCT_BOTH:
/* "" */
*st = 0;
break;
case XCT_UNKNOWN_BO:
if(xer_check_tag(chunk_buf, chunk_size, "true")
!= XCT_BOTH)
return XPBD_BROKEN_ENCODING;
/* "" */
*st = 1; /* Or 0xff as in DER?.. */
break;
default:
return XPBD_BROKEN_ENCODING;
}
return XPBD_BODY_CONSUMED;
} else {
return XPBD_BROKEN_ENCODING;
}
}
asn_dec_rval_t
BOOLEAN_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
const void *buf_ptr, size_t size) {
return xer_decode_primitive(opt_codec_ctx, td,
sptr, sizeof(BOOLEAN_t), opt_mname, buf_ptr, size,
BOOLEAN__xer_body_decode);
}
asn_enc_rval_t
BOOLEAN_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
asn_enc_rval_t er;
(void)ilevel;
(void)flags;
if(!st) ASN__ENCODE_FAILED;
if(*st) {
ASN__CALLBACK("", 7);
er.encoded = 7;
} else {
ASN__CALLBACK("", 8);
er.encoded = 8;
}
ASN__ENCODED_OK(er);
cb_failed:
ASN__ENCODE_FAILED;
}
int
BOOLEAN_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
const char *buf;
size_t buflen;
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(st) {
if(*st) {
buf = "TRUE";
buflen = 4;
} else {
buf = "FALSE";
buflen = 5;
}
} else {
buf = "";
buflen = 8;
}
return (cb(buf, buflen, app_key) < 0) ? -1 : 0;
}
void
BOOLEAN_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
if(td && ptr && !contents_only) {
FREEMEM(ptr);
}
}
asn_dec_rval_t
BOOLEAN_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_dec_rval_t rv;
BOOLEAN_t *st = (BOOLEAN_t *)*sptr;
(void)opt_codec_ctx;
(void)constraints;
if(!st) {
st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st)));
if(!st) ASN__DECODE_FAILED;
}
/*
* Extract a single bit
*/
switch(per_get_few_bits(pd, 1)) {
case 1: *st = 1; break;
case 0: *st = 0; break;
case -1: default: ASN__DECODE_STARVED;
}
ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE");
rv.code = RC_OK;
rv.consumed = 1;
return rv;
}
asn_enc_rval_t
BOOLEAN_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
asn_enc_rval_t er = { 0, 0, 0 };
(void)constraints;
if(!st) ASN__ENCODE_FAILED;
if(per_put_few_bits(po, *st ? 1 : 0, 1))
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/BOOLEAN.h 0000664 0000000 0000000 00000001573 15245442746 0025565 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _BOOLEAN_H_
#define _BOOLEAN_H_
#include
#ifdef __cplusplus
extern "C" {
#endif
/*
* The underlying integer may contain various values, but everything
* non-zero is capped to 0xff by the DER encoder. The BER decoder may
* yield non-zero values different from 1, beware.
*/
typedef int BOOLEAN_t;
extern asn_TYPE_descriptor_t asn_DEF_BOOLEAN;
asn_struct_free_f BOOLEAN_free;
asn_struct_print_f BOOLEAN_print;
ber_type_decoder_f BOOLEAN_decode_ber;
der_type_encoder_f BOOLEAN_encode_der;
xer_type_decoder_f BOOLEAN_decode_xer;
xer_type_encoder_f BOOLEAN_encode_xer;
per_type_decoder_f BOOLEAN_decode_uper;
per_type_encoder_f BOOLEAN_encode_uper;
#ifdef __cplusplus
}
#endif
#endif /* _BOOLEAN_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/C.c 0000664 0000000 0000000 00000031630 15245442746 0024660 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#include "C.h"
static int
memb_a_constraint_2(asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
size_t size;
if(!sptr) {
ASN__CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
/* Determine the number of elements */
size = _A_CSEQUENCE_FROM_VOID(sptr)->count;
if((size <= 5)) {
/* Perform validation of the inner elements */
return td->check_constraints(td, sptr, ctfailcb, app_key);
} else {
ASN__CTFAIL(app_key, td, sptr,
"%s: constraint failed (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
}
static int
memb_c_constraint_2(asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
long value;
if(!sptr) {
ASN__CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
value = *(const long *)sptr;
if((value >= -40 && value <= 40)) {
/* Constraint check succeeded */
return 0;
} else {
ASN__CTFAIL(app_key, td, sptr,
"%s: constraint failed (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
}
static int
memb_a_constraint_8(asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
size_t size;
if(!sptr) {
ASN__CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
/* Determine the number of elements */
size = _A_CSEQUENCE_FROM_VOID(sptr)->count;
if((size == 3)) {
/* Perform validation of the inner elements */
return td->check_constraints(td, sptr, ctfailcb, app_key);
} else {
ASN__CTFAIL(app_key, td, sptr,
"%s: constraint failed (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
}
static asn_per_constraints_t asn_PER_type_a_constr_3 GCC_NOTUSED = {
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
{ APC_CONSTRAINED, 3, 3, 0, 5 } /* (SIZE(0..5)) */,
0, 0 /* No PER value map */
};
static asn_per_constraints_t asn_PER_memb_a_constr_3 GCC_NOTUSED = {
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
{ APC_CONSTRAINED, 3, 3, 0, 5 } /* (SIZE(0..5)) */,
0, 0 /* No PER value map */
};
static asn_per_constraints_t asn_PER_memb_c_constr_6 GCC_NOTUSED = {
{ APC_CONSTRAINED, 7, 7, -40, 40 } /* (-40..40) */,
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
0, 0 /* No PER value map */
};
static asn_per_constraints_t asn_PER_type_a_constr_9 GCC_NOTUSED = {
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
{ APC_CONSTRAINED, 0, 0, 3, 3 } /* (SIZE(3..3)) */,
0, 0 /* No PER value map */
};
static asn_per_constraints_t asn_PER_memb_a_constr_9 GCC_NOTUSED = {
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
{ APC_CONSTRAINED, 0, 0, 3, 3 } /* (SIZE(3..3)) */,
0, 0 /* No PER value map */
};
static asn_per_constraints_t asn_PER_type_c_constr_8 GCC_NOTUSED = {
{ APC_CONSTRAINED, 1, 1, 0, 1 } /* (0..1) */,
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
0, 0 /* No PER value map */
};
static asn_TYPE_member_t asn_MBR_a_3[] = {
{ ATF_POINTER, 0, 0,
(ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
0,
&asn_DEF_F,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
""
},
};
static const ber_tlv_tag_t asn_DEF_a_tags_3[] = {
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
};
static asn_SET_OF_specifics_t asn_SPC_a_specs_3 = {
sizeof(struct C__a__a),
offsetof(struct C__a__a, _asn_ctx),
0, /* XER encoding is XMLDelimitedItemList */
};
static /* Use -fall-defs-global to expose */
asn_TYPE_descriptor_t asn_DEF_a_3 = {
"a",
"a",
SEQUENCE_OF_free,
SEQUENCE_OF_print,
SEQUENCE_OF_constraint,
SEQUENCE_OF_decode_ber,
SEQUENCE_OF_encode_der,
SEQUENCE_OF_decode_xer,
SEQUENCE_OF_encode_xer,
SEQUENCE_OF_decode_uper,
SEQUENCE_OF_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_a_tags_3,
sizeof(asn_DEF_a_tags_3)
/sizeof(asn_DEF_a_tags_3[0]) - 1, /* 1 */
asn_DEF_a_tags_3, /* Same as above */
sizeof(asn_DEF_a_tags_3)
/sizeof(asn_DEF_a_tags_3[0]), /* 2 */
&asn_PER_type_a_constr_3,
asn_MBR_a_3,
1, /* Single element */
&asn_SPC_a_specs_3 /* Additional specs */
};
static int asn_DFL_6_set_0(int set_value, void **sptr) {
long *st = *sptr;
if(!st) {
if(!set_value) return -1; /* Not a default value */
st = (*sptr = CALLOC(1, sizeof(*st)));
if(!st) return -1;
}
if(set_value) {
/* Install default value 0 */
*st = 0;
return 0;
} else {
/* Test default value 0 */
return (*st == 0);
}
}
static asn_TYPE_member_t asn_MBR_a_2[] = {
{ ATF_NOFLAGS, 0, offsetof(struct C__a, a),
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
0,
&asn_DEF_a_3,
memb_a_constraint_2,
&asn_PER_memb_a_constr_3,
0,
"a"
},
{ ATF_POINTER, 2, offsetof(struct C__a, b),
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
-1, /* IMPLICIT tag at current level */
&asn_DEF_BOOLEAN,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"b"
},
{ ATF_NOFLAGS, 1, offsetof(struct C__a, c),
(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
-1, /* IMPLICIT tag at current level */
&asn_DEF_NativeInteger,
memb_c_constraint_2,
&asn_PER_memb_c_constr_6,
asn_DFL_6_set_0, /* DEFAULT 0 */
"c"
},
};
static const int asn_MAP_a_oms_2[] = { 1, 2 };
static const ber_tlv_tag_t asn_DEF_a_tags_2[] = {
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
};
static const asn_TYPE_tag2member_t asn_MAP_a_tag2el_2[] = {
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* a */
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* b */
{ (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 } /* c */
};
static asn_SEQUENCE_specifics_t asn_SPC_a_specs_2 = {
sizeof(struct C__a),
offsetof(struct C__a, _asn_ctx),
asn_MAP_a_tag2el_2,
3, /* Count of tags in the map */
asn_MAP_a_oms_2, /* Optional members */
2, 0, /* Root/Additions */
-1, /* Start extensions */
-1 /* Stop extensions */
};
static /* Use -fall-defs-global to expose */
asn_TYPE_descriptor_t asn_DEF_a_2 = {
"a",
"a",
SEQUENCE_free,
SEQUENCE_print,
SEQUENCE_constraint,
SEQUENCE_decode_ber,
SEQUENCE_encode_der,
SEQUENCE_decode_xer,
SEQUENCE_encode_xer,
SEQUENCE_decode_uper,
SEQUENCE_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_a_tags_2,
sizeof(asn_DEF_a_tags_2)
/sizeof(asn_DEF_a_tags_2[0]) - 1, /* 1 */
asn_DEF_a_tags_2, /* Same as above */
sizeof(asn_DEF_a_tags_2)
/sizeof(asn_DEF_a_tags_2[0]), /* 2 */
0, /* No PER visible constraints */
asn_MBR_a_2,
3, /* Elements count */
&asn_SPC_a_specs_2 /* Additional specs */
};
static asn_TYPE_member_t asn_MBR_a_9[] = {
{ ATF_POINTER, 0, 0,
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)),
0,
&asn_DEF_D,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
""
},
};
static const ber_tlv_tag_t asn_DEF_a_tags_9[] = {
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
};
static asn_SET_OF_specifics_t asn_SPC_a_specs_9 = {
sizeof(struct C__c__a),
offsetof(struct C__c__a, _asn_ctx),
0, /* XER encoding is XMLDelimitedItemList */
};
static /* Use -fall-defs-global to expose */
asn_TYPE_descriptor_t asn_DEF_a_9 = {
"a",
"a",
SEQUENCE_OF_free,
SEQUENCE_OF_print,
SEQUENCE_OF_constraint,
SEQUENCE_OF_decode_ber,
SEQUENCE_OF_encode_der,
SEQUENCE_OF_decode_xer,
SEQUENCE_OF_encode_xer,
SEQUENCE_OF_decode_uper,
SEQUENCE_OF_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_a_tags_9,
sizeof(asn_DEF_a_tags_9)
/sizeof(asn_DEF_a_tags_9[0]) - 1, /* 1 */
asn_DEF_a_tags_9, /* Same as above */
sizeof(asn_DEF_a_tags_9)
/sizeof(asn_DEF_a_tags_9[0]), /* 2 */
&asn_PER_type_a_constr_9,
asn_MBR_a_9,
1, /* Single element */
&asn_SPC_a_specs_9 /* Additional specs */
};
static asn_TYPE_member_t asn_MBR_c_8[] = {
{ ATF_NOFLAGS, 0, offsetof(struct C__c, choice.a),
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
0,
&asn_DEF_a_9,
memb_a_constraint_8,
&asn_PER_memb_a_constr_9,
0,
"a"
},
{ ATF_NOFLAGS, 0, offsetof(struct C__c, choice.b),
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
-1, /* IMPLICIT tag at current level */
&asn_DEF_E,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"b"
},
};
static const asn_TYPE_tag2member_t asn_MAP_c_tag2el_8[] = {
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* a */
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* b */
};
static asn_CHOICE_specifics_t asn_SPC_c_specs_8 = {
sizeof(struct C__c),
offsetof(struct C__c, _asn_ctx),
offsetof(struct C__c, present),
sizeof(((struct C__c *)0)->present),
asn_MAP_c_tag2el_8,
2, /* Count of tags in the map */
0,
-1 /* Extensions start */
};
static /* Use -fall-defs-global to expose */
asn_TYPE_descriptor_t asn_DEF_c_8 = {
"c",
"c",
CHOICE_free,
CHOICE_print,
CHOICE_constraint,
CHOICE_decode_ber,
CHOICE_encode_der,
CHOICE_decode_xer,
CHOICE_encode_xer,
CHOICE_decode_uper,
CHOICE_encode_uper,
CHOICE_outmost_tag,
0, /* No effective tags (pointer) */
0, /* No effective tags (count) */
0, /* No tags (pointer) */
0, /* No tags (count) */
&asn_PER_type_c_constr_8,
asn_MBR_c_8,
2, /* Elements count */
&asn_SPC_c_specs_8 /* Additional specs */
};
static asn_TYPE_member_t asn_MBR_d_12[] = {
{ ATF_NOFLAGS, 0, offsetof(struct C__d, a),
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
-1, /* IMPLICIT tag at current level */
&asn_DEF_E,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"a"
},
};
static const ber_tlv_tag_t asn_DEF_d_tags_12[] = {
(ASN_TAG_CLASS_CONTEXT | (3 << 2)),
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
};
static const asn_TYPE_tag2member_t asn_MAP_d_tag2el_12[] = {
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 } /* a */
};
static asn_SEQUENCE_specifics_t asn_SPC_d_specs_12 = {
sizeof(struct C__d),
offsetof(struct C__d, _asn_ctx),
asn_MAP_d_tag2el_12,
1, /* Count of tags in the map */
0, 0, 0, /* Optional elements (not needed) */
-1, /* Start extensions */
-1 /* Stop extensions */
};
static /* Use -fall-defs-global to expose */
asn_TYPE_descriptor_t asn_DEF_d_12 = {
"d",
"d",
SEQUENCE_free,
SEQUENCE_print,
SEQUENCE_constraint,
SEQUENCE_decode_ber,
SEQUENCE_encode_der,
SEQUENCE_decode_xer,
SEQUENCE_encode_xer,
SEQUENCE_decode_uper,
SEQUENCE_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_d_tags_12,
sizeof(asn_DEF_d_tags_12)
/sizeof(asn_DEF_d_tags_12[0]) - 1, /* 1 */
asn_DEF_d_tags_12, /* Same as above */
sizeof(asn_DEF_d_tags_12)
/sizeof(asn_DEF_d_tags_12[0]), /* 2 */
0, /* No PER visible constraints */
asn_MBR_d_12,
1, /* Elements count */
&asn_SPC_d_specs_12 /* Additional specs */
};
static asn_TYPE_member_t asn_MBR_C_1[] = {
{ ATF_POINTER, 1, offsetof(struct C, a),
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
0,
&asn_DEF_a_2,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"a"
},
{ ATF_NOFLAGS, 0, offsetof(struct C, b),
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
-1, /* IMPLICIT tag at current level */
&asn_DEF_G,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"b"
},
{ ATF_NOFLAGS, 0, offsetof(struct C, c),
(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
+1, /* EXPLICIT tag at current level */
&asn_DEF_c_8,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"c"
},
{ ATF_NOFLAGS, 0, offsetof(struct C, d),
(ASN_TAG_CLASS_CONTEXT | (3 << 2)),
0,
&asn_DEF_d_12,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"d"
},
};
static const int asn_MAP_C_oms_1[] = { 0 };
static const ber_tlv_tag_t asn_DEF_C_tags_1[] = {
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
};
static const asn_TYPE_tag2member_t asn_MAP_C_tag2el_1[] = {
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* a */
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* b */
{ (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 }, /* c */
{ (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 3, 0, 0 } /* d */
};
static asn_SEQUENCE_specifics_t asn_SPC_C_specs_1 = {
sizeof(struct C),
offsetof(struct C, _asn_ctx),
asn_MAP_C_tag2el_1,
4, /* Count of tags in the map */
asn_MAP_C_oms_1, /* Optional members */
1, 0, /* Root/Additions */
-1, /* Start extensions */
-1 /* Stop extensions */
};
asn_TYPE_descriptor_t asn_DEF_C = {
"C",
"C",
SEQUENCE_free,
SEQUENCE_print,
SEQUENCE_constraint,
SEQUENCE_decode_ber,
SEQUENCE_encode_der,
SEQUENCE_decode_xer,
SEQUENCE_encode_xer,
SEQUENCE_decode_uper,
SEQUENCE_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_C_tags_1,
sizeof(asn_DEF_C_tags_1)
/sizeof(asn_DEF_C_tags_1[0]), /* 1 */
asn_DEF_C_tags_1, /* Same as above */
sizeof(asn_DEF_C_tags_1)
/sizeof(asn_DEF_C_tags_1[0]), /* 1 */
0, /* No PER visible constraints */
asn_MBR_C_1,
4, /* Elements count */
&asn_SPC_C_specs_1 /* Additional specs */
};
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/C.h 0000664 0000000 0000000 00000003214 15245442746 0024662 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#ifndef _C_H_
#define _C_H_
#include "asn_application.h"
/* Including external dependencies */
#include "G.h"
#include "BOOLEAN.h"
#include "NativeInteger.h"
#include "F.h"
#include "asn_SEQUENCE_OF.h"
#include "constr_SEQUENCE_OF.h"
#include "constr_SEQUENCE.h"
#include "E.h"
#include "D.h"
#include "constr_CHOICE.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Dependencies */
typedef enum C__c_PR {
C__c_PR_NOTHING, /* No components present */
C__c_PR_a,
C__c_PR_b
} C__c_PR;
/* C */
typedef struct C {
struct C__a {
struct C__a__a {
A_SEQUENCE_OF(F_t) list;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} a;
BOOLEAN_t *b /* OPTIONAL */;
long c /* DEFAULT 0 */;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} *a;
G_t b;
struct C__c {
C__c_PR present;
union C__c_u {
struct C__c__a {
A_SEQUENCE_OF(D_t) list;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} a;
E_t b;
} choice;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} c;
struct C__d {
E_t a;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} d;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} C_t;
/* Implementation */
extern asn_TYPE_descriptor_t asn_DEF_C;
#ifdef __cplusplus
}
#endif
#endif /* _C_H_ */
#include "asn_internal.h"
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/D.c 0000664 0000000 0000000 00000010601 15245442746 0024654 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#include "D.h"
int
D_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
size_t size;
if(!sptr) {
ASN__CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
size = st->size;
if((size >= 1 && size <= 16)) {
/* Constraint check succeeded */
return 0;
} else {
ASN__CTFAIL(app_key, td, sptr,
"%s: constraint failed (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
}
/*
* This type is implemented using OCTET_STRING,
* so here we adjust the DEF accordingly.
*/
static void
D_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
td->free_struct = asn_DEF_OCTET_STRING.free_struct;
td->print_struct = asn_DEF_OCTET_STRING.print_struct;
td->check_constraints = asn_DEF_OCTET_STRING.check_constraints;
td->ber_decoder = asn_DEF_OCTET_STRING.ber_decoder;
td->der_encoder = asn_DEF_OCTET_STRING.der_encoder;
td->xer_decoder = asn_DEF_OCTET_STRING.xer_decoder;
td->xer_encoder = asn_DEF_OCTET_STRING.xer_encoder;
td->uper_decoder = asn_DEF_OCTET_STRING.uper_decoder;
td->uper_encoder = asn_DEF_OCTET_STRING.uper_encoder;
if(!td->per_constraints)
td->per_constraints = asn_DEF_OCTET_STRING.per_constraints;
td->elements = asn_DEF_OCTET_STRING.elements;
td->elements_count = asn_DEF_OCTET_STRING.elements_count;
td->specifics = asn_DEF_OCTET_STRING.specifics;
}
void
D_free(asn_TYPE_descriptor_t *td,
void *struct_ptr, int contents_only) {
D_1_inherit_TYPE_descriptor(td);
td->free_struct(td, struct_ptr, contents_only);
}
int
D_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
D_1_inherit_TYPE_descriptor(td);
return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
}
asn_dec_rval_t
D_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **structure, const void *bufptr, size_t size, int tag_mode) {
D_1_inherit_TYPE_descriptor(td);
return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
}
asn_enc_rval_t
D_encode_der(asn_TYPE_descriptor_t *td,
void *structure, int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
D_1_inherit_TYPE_descriptor(td);
return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
}
asn_dec_rval_t
D_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **structure, const char *opt_mname, const void *bufptr, size_t size) {
D_1_inherit_TYPE_descriptor(td);
return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
}
asn_enc_rval_t
D_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
D_1_inherit_TYPE_descriptor(td);
return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
}
asn_dec_rval_t
D_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {
D_1_inherit_TYPE_descriptor(td);
return td->uper_decoder(opt_codec_ctx, td, constraints, structure, per_data);
}
asn_enc_rval_t
D_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints,
void *structure, asn_per_outp_t *per_out) {
D_1_inherit_TYPE_descriptor(td);
return td->uper_encoder(td, constraints, structure, per_out);
}
static asn_per_constraints_t asn_PER_type_D_constr_1 GCC_NOTUSED = {
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
{ APC_CONSTRAINED, 4, 4, 1, 16 } /* (SIZE(1..16)) */,
0, 0 /* No PER value map */
};
static const ber_tlv_tag_t asn_DEF_D_tags_1[] = {
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
};
asn_TYPE_descriptor_t asn_DEF_D = {
"D",
"D",
D_free,
D_print,
D_constraint,
D_decode_ber,
D_encode_der,
D_decode_xer,
D_encode_xer,
D_decode_uper,
D_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_D_tags_1,
sizeof(asn_DEF_D_tags_1)
/sizeof(asn_DEF_D_tags_1[0]), /* 1 */
asn_DEF_D_tags_1, /* Same as above */
sizeof(asn_DEF_D_tags_1)
/sizeof(asn_DEF_D_tags_1[0]), /* 1 */
&asn_PER_type_D_constr_1,
0, 0, /* No members */
0 /* No specifics */
};
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/D.h 0000664 0000000 0000000 00000001461 15245442746 0024665 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#ifndef _D_H_
#define _D_H_
#include "asn_application.h"
/* Including external dependencies */
#include "OCTET_STRING.h"
#ifdef __cplusplus
extern "C" {
#endif
/* D */
typedef OCTET_STRING_t D_t;
/* Implementation */
extern asn_TYPE_descriptor_t asn_DEF_D;
asn_struct_free_f D_free;
asn_struct_print_f D_print;
asn_constr_check_f D_constraint;
ber_type_decoder_f D_decode_ber;
der_type_encoder_f D_encode_der;
xer_type_decoder_f D_decode_xer;
xer_type_encoder_f D_encode_xer;
per_type_decoder_f D_decode_uper;
per_type_encoder_f D_encode_uper;
#ifdef __cplusplus
}
#endif
#endif /* _D_H_ */
#include "asn_internal.h"
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/E.c 0000664 0000000 0000000 00000007556 15245442746 0024674 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#include "E.h"
int
E_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
/* Replace with underlying type checker */
td->check_constraints = asn_DEF_BOOLEAN.check_constraints;
return td->check_constraints(td, sptr, ctfailcb, app_key);
}
/*
* This type is implemented using BOOLEAN,
* so here we adjust the DEF accordingly.
*/
static void
E_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
td->free_struct = asn_DEF_BOOLEAN.free_struct;
td->print_struct = asn_DEF_BOOLEAN.print_struct;
td->check_constraints = asn_DEF_BOOLEAN.check_constraints;
td->ber_decoder = asn_DEF_BOOLEAN.ber_decoder;
td->der_encoder = asn_DEF_BOOLEAN.der_encoder;
td->xer_decoder = asn_DEF_BOOLEAN.xer_decoder;
td->xer_encoder = asn_DEF_BOOLEAN.xer_encoder;
td->uper_decoder = asn_DEF_BOOLEAN.uper_decoder;
td->uper_encoder = asn_DEF_BOOLEAN.uper_encoder;
if(!td->per_constraints)
td->per_constraints = asn_DEF_BOOLEAN.per_constraints;
td->elements = asn_DEF_BOOLEAN.elements;
td->elements_count = asn_DEF_BOOLEAN.elements_count;
td->specifics = asn_DEF_BOOLEAN.specifics;
}
void
E_free(asn_TYPE_descriptor_t *td,
void *struct_ptr, int contents_only) {
E_1_inherit_TYPE_descriptor(td);
td->free_struct(td, struct_ptr, contents_only);
}
int
E_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
E_1_inherit_TYPE_descriptor(td);
return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
}
asn_dec_rval_t
E_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **structure, const void *bufptr, size_t size, int tag_mode) {
E_1_inherit_TYPE_descriptor(td);
return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
}
asn_enc_rval_t
E_encode_der(asn_TYPE_descriptor_t *td,
void *structure, int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
E_1_inherit_TYPE_descriptor(td);
return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
}
asn_dec_rval_t
E_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **structure, const char *opt_mname, const void *bufptr, size_t size) {
E_1_inherit_TYPE_descriptor(td);
return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
}
asn_enc_rval_t
E_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
E_1_inherit_TYPE_descriptor(td);
return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
}
asn_dec_rval_t
E_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {
E_1_inherit_TYPE_descriptor(td);
return td->uper_decoder(opt_codec_ctx, td, constraints, structure, per_data);
}
asn_enc_rval_t
E_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints,
void *structure, asn_per_outp_t *per_out) {
E_1_inherit_TYPE_descriptor(td);
return td->uper_encoder(td, constraints, structure, per_out);
}
static const ber_tlv_tag_t asn_DEF_E_tags_1[] = {
(ASN_TAG_CLASS_UNIVERSAL | (1 << 2))
};
asn_TYPE_descriptor_t asn_DEF_E = {
"E",
"E",
E_free,
E_print,
E_constraint,
E_decode_ber,
E_encode_der,
E_decode_xer,
E_encode_xer,
E_decode_uper,
E_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_E_tags_1,
sizeof(asn_DEF_E_tags_1)
/sizeof(asn_DEF_E_tags_1[0]), /* 1 */
asn_DEF_E_tags_1, /* Same as above */
sizeof(asn_DEF_E_tags_1)
/sizeof(asn_DEF_E_tags_1[0]), /* 1 */
0, /* No PER visible constraints */
0, 0, /* No members */
0 /* No specifics */
};
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/E.h 0000664 0000000 0000000 00000001447 15245442746 0024672 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#ifndef _E_H_
#define _E_H_
#include "asn_application.h"
/* Including external dependencies */
#include "BOOLEAN.h"
#ifdef __cplusplus
extern "C" {
#endif
/* E */
typedef BOOLEAN_t E_t;
/* Implementation */
extern asn_TYPE_descriptor_t asn_DEF_E;
asn_struct_free_f E_free;
asn_struct_print_f E_print;
asn_constr_check_f E_constraint;
ber_type_decoder_f E_decode_ber;
der_type_encoder_f E_encode_der;
xer_type_decoder_f E_decode_xer;
xer_type_encoder_f E_encode_xer;
per_type_decoder_f E_decode_uper;
per_type_encoder_f E_encode_uper;
#ifdef __cplusplus
}
#endif
#endif /* _E_H_ */
#include "asn_internal.h"
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/F.c 0000664 0000000 0000000 00000010640 15245442746 0024661 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#include "F.h"
int
F_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
long value;
if(!sptr) {
ASN__CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
value = *(const long *)sptr;
if((value >= (-2147483647L - 1) && value <= 2147483647)) {
/* Constraint check succeeded */
return 0;
} else {
ASN__CTFAIL(app_key, td, sptr,
"%s: constraint failed (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
}
/*
* This type is implemented using NativeInteger,
* so here we adjust the DEF accordingly.
*/
static void
F_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
td->free_struct = asn_DEF_NativeInteger.free_struct;
td->print_struct = asn_DEF_NativeInteger.print_struct;
td->check_constraints = asn_DEF_NativeInteger.check_constraints;
td->ber_decoder = asn_DEF_NativeInteger.ber_decoder;
td->der_encoder = asn_DEF_NativeInteger.der_encoder;
td->xer_decoder = asn_DEF_NativeInteger.xer_decoder;
td->xer_encoder = asn_DEF_NativeInteger.xer_encoder;
td->uper_decoder = asn_DEF_NativeInteger.uper_decoder;
td->uper_encoder = asn_DEF_NativeInteger.uper_encoder;
if(!td->per_constraints)
td->per_constraints = asn_DEF_NativeInteger.per_constraints;
td->elements = asn_DEF_NativeInteger.elements;
td->elements_count = asn_DEF_NativeInteger.elements_count;
td->specifics = asn_DEF_NativeInteger.specifics;
}
void
F_free(asn_TYPE_descriptor_t *td,
void *struct_ptr, int contents_only) {
F_1_inherit_TYPE_descriptor(td);
td->free_struct(td, struct_ptr, contents_only);
}
int
F_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
F_1_inherit_TYPE_descriptor(td);
return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
}
asn_dec_rval_t
F_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **structure, const void *bufptr, size_t size, int tag_mode) {
F_1_inherit_TYPE_descriptor(td);
return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
}
asn_enc_rval_t
F_encode_der(asn_TYPE_descriptor_t *td,
void *structure, int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
F_1_inherit_TYPE_descriptor(td);
return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
}
asn_dec_rval_t
F_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **structure, const char *opt_mname, const void *bufptr, size_t size) {
F_1_inherit_TYPE_descriptor(td);
return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
}
asn_enc_rval_t
F_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
F_1_inherit_TYPE_descriptor(td);
return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
}
asn_dec_rval_t
F_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {
F_1_inherit_TYPE_descriptor(td);
return td->uper_decoder(opt_codec_ctx, td, constraints, structure, per_data);
}
asn_enc_rval_t
F_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints,
void *structure, asn_per_outp_t *per_out) {
F_1_inherit_TYPE_descriptor(td);
return td->uper_encoder(td, constraints, structure, per_out);
}
static asn_per_constraints_t asn_PER_type_F_constr_1 GCC_NOTUSED = {
{ APC_CONSTRAINED, 32, -1, (-2147483647L - 1), 2147483647 } /* (-2147483648..2147483647) */,
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
0, 0 /* No PER value map */
};
static const ber_tlv_tag_t asn_DEF_F_tags_1[] = {
(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
};
asn_TYPE_descriptor_t asn_DEF_F = {
"F",
"F",
F_free,
F_print,
F_constraint,
F_decode_ber,
F_encode_der,
F_decode_xer,
F_encode_xer,
F_decode_uper,
F_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_F_tags_1,
sizeof(asn_DEF_F_tags_1)
/sizeof(asn_DEF_F_tags_1[0]), /* 1 */
asn_DEF_F_tags_1, /* Same as above */
sizeof(asn_DEF_F_tags_1)
/sizeof(asn_DEF_F_tags_1[0]), /* 1 */
&asn_PER_type_F_constr_1,
0, 0, /* No members */
0 /* No specifics */
};
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/F.h 0000664 0000000 0000000 00000001450 15245442746 0024665 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#ifndef _F_H_
#define _F_H_
#include "asn_application.h"
/* Including external dependencies */
#include "NativeInteger.h"
#ifdef __cplusplus
extern "C" {
#endif
/* F */
typedef long F_t;
/* Implementation */
extern asn_TYPE_descriptor_t asn_DEF_F;
asn_struct_free_f F_free;
asn_struct_print_f F_print;
asn_constr_check_f F_constraint;
ber_type_decoder_f F_decode_ber;
der_type_encoder_f F_encode_der;
xer_type_decoder_f F_decode_xer;
xer_type_encoder_f F_encode_xer;
per_type_decoder_f F_decode_uper;
per_type_encoder_f F_encode_uper;
#ifdef __cplusplus
}
#endif
#endif /* _F_H_ */
#include "asn_internal.h"
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/G.c 0000664 0000000 0000000 00000010533 15245442746 0024663 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#include "G.h"
int
G_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
if(!sptr) {
ASN__CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
/* Constraint check succeeded */
return 0;
}
/*
* This type is implemented using NativeInteger,
* so here we adjust the DEF accordingly.
*/
static void
G_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
td->free_struct = asn_DEF_NativeInteger.free_struct;
td->print_struct = asn_DEF_NativeInteger.print_struct;
td->check_constraints = asn_DEF_NativeInteger.check_constraints;
td->ber_decoder = asn_DEF_NativeInteger.ber_decoder;
td->der_encoder = asn_DEF_NativeInteger.der_encoder;
td->xer_decoder = asn_DEF_NativeInteger.xer_decoder;
td->xer_encoder = asn_DEF_NativeInteger.xer_encoder;
td->uper_decoder = asn_DEF_NativeInteger.uper_decoder;
td->uper_encoder = asn_DEF_NativeInteger.uper_encoder;
if(!td->per_constraints)
td->per_constraints = asn_DEF_NativeInteger.per_constraints;
td->elements = asn_DEF_NativeInteger.elements;
td->elements_count = asn_DEF_NativeInteger.elements_count;
/* td->specifics = asn_DEF_NativeInteger.specifics; // Defined explicitly */
}
void
G_free(asn_TYPE_descriptor_t *td,
void *struct_ptr, int contents_only) {
G_1_inherit_TYPE_descriptor(td);
td->free_struct(td, struct_ptr, contents_only);
}
int
G_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
G_1_inherit_TYPE_descriptor(td);
return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
}
asn_dec_rval_t
G_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **structure, const void *bufptr, size_t size, int tag_mode) {
G_1_inherit_TYPE_descriptor(td);
return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
}
asn_enc_rval_t
G_encode_der(asn_TYPE_descriptor_t *td,
void *structure, int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
G_1_inherit_TYPE_descriptor(td);
return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
}
asn_dec_rval_t
G_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **structure, const char *opt_mname, const void *bufptr, size_t size) {
G_1_inherit_TYPE_descriptor(td);
return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
}
asn_enc_rval_t
G_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
G_1_inherit_TYPE_descriptor(td);
return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
}
asn_dec_rval_t
G_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {
G_1_inherit_TYPE_descriptor(td);
return td->uper_decoder(opt_codec_ctx, td, constraints, structure, per_data);
}
asn_enc_rval_t
G_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints,
void *structure, asn_per_outp_t *per_out) {
G_1_inherit_TYPE_descriptor(td);
return td->uper_encoder(td, constraints, structure, per_out);
}
static asn_per_constraints_t asn_PER_type_G_constr_1 GCC_NOTUSED = {
{ APC_CONSTRAINED, 32, -1, 0, 4294967295 } /* (0..4294967295) */,
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
0, 0 /* No PER value map */
};
static const asn_INTEGER_specifics_t asn_SPC_G_specs_1 = {
0, 0, 0, 0, 0,
0, /* Native long size */
1 /* Unsigned representation */
};
static const ber_tlv_tag_t asn_DEF_G_tags_1[] = {
(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
};
asn_TYPE_descriptor_t asn_DEF_G = {
"G",
"G",
G_free,
G_print,
G_constraint,
G_decode_ber,
G_encode_der,
G_decode_xer,
G_encode_xer,
G_decode_uper,
G_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_G_tags_1,
sizeof(asn_DEF_G_tags_1)
/sizeof(asn_DEF_G_tags_1[0]), /* 1 */
asn_DEF_G_tags_1, /* Same as above */
sizeof(asn_DEF_G_tags_1)
/sizeof(asn_DEF_G_tags_1[0]), /* 1 */
&asn_PER_type_G_constr_1,
0, 0, /* No members */
&asn_SPC_G_specs_1 /* Additional specs */
};
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/G.h 0000664 0000000 0000000 00000001461 15245442746 0024670 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#ifndef _G_H_
#define _G_H_
#include "asn_application.h"
/* Including external dependencies */
#include "NativeInteger.h"
#ifdef __cplusplus
extern "C" {
#endif
/* G */
typedef unsigned long G_t;
/* Implementation */
extern asn_TYPE_descriptor_t asn_DEF_G;
asn_struct_free_f G_free;
asn_struct_print_f G_print;
asn_constr_check_f G_constraint;
ber_type_decoder_f G_decode_ber;
der_type_encoder_f G_encode_der;
xer_type_decoder_f G_decode_xer;
xer_type_encoder_f G_encode_xer;
per_type_decoder_f G_decode_uper;
per_type_encoder_f G_encode_uper;
#ifdef __cplusplus
}
#endif
#endif /* _G_H_ */
#include "asn_internal.h"
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/INTEGER.c 0000664 0000000 0000000 00000061323 15245442746 0025575 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003-2014 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include /* Encoder and decoder of a primitive type */
#include
/*
* INTEGER basic type description.
*/
static const ber_tlv_tag_t asn_DEF_INTEGER_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
};
asn_TYPE_descriptor_t asn_DEF_INTEGER = {
"INTEGER",
"INTEGER",
ASN__PRIMITIVE_TYPE_free,
INTEGER_print,
asn_generic_no_constraint,
ber_decode_primitive,
INTEGER_encode_der,
INTEGER_decode_xer,
INTEGER_encode_xer,
#ifdef ASN_DISABLE_PER_SUPPORT
0,
0,
#else
INTEGER_decode_uper, /* Unaligned PER decoder */
INTEGER_encode_uper, /* Unaligned PER encoder */
#endif /* ASN_DISABLE_PER_SUPPORT */
0, /* Use generic outmost tag fetcher */
asn_DEF_INTEGER_tags,
sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
asn_DEF_INTEGER_tags, /* Same as above */
sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
0, /* No PER visible constraints */
0, 0, /* No members */
0 /* No specifics */
};
/*
* Encode INTEGER type using DER.
*/
asn_enc_rval_t
INTEGER_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
INTEGER_t *st = (INTEGER_t *)sptr;
ASN_DEBUG("%s %s as INTEGER (tm=%d)",
cb?"Encoding":"Estimating", td->name, tag_mode);
/*
* Canonicalize integer in the buffer.
* (Remove too long sign extension, remove some first 0x00 bytes)
*/
if(st->buf) {
uint8_t *buf = st->buf;
uint8_t *end1 = buf + st->size - 1;
int shift;
/* Compute the number of superfluous leading bytes */
for(; buf < end1; buf++) {
/*
* If the contents octets of an integer value encoding
* consist of more than one octet, then the bits of the
* first octet and bit 8 of the second octet:
* a) shall not all be ones; and
* b) shall not all be zero.
*/
switch(*buf) {
case 0x00: if((buf[1] & 0x80) == 0)
continue;
break;
case 0xff: if((buf[1] & 0x80))
continue;
break;
}
break;
}
/* Remove leading superfluous bytes from the integer */
shift = buf - st->buf;
if(shift) {
uint8_t *nb = st->buf;
uint8_t *end;
st->size -= shift; /* New size, minus bad bytes */
end = nb + st->size;
for(; nb < end; nb++, buf++)
*nb = *buf;
}
} /* if(1) */
return der_encode_primitive(td, sptr, tag_mode, tag, cb, app_key);
}
static const asn_INTEGER_enum_map_t *INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop);
/*
* INTEGER specific human-readable output.
*/
static ssize_t
INTEGER__dump(const asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
char scratch[32]; /* Enough for 64-bit integer */
uint8_t *buf = st->buf;
uint8_t *buf_end = st->buf + st->size;
signed long value;
ssize_t wrote = 0;
char *p;
int ret;
if(specs && specs->field_unsigned)
ret = asn_INTEGER2ulong(st, (unsigned long *)&value);
else
ret = asn_INTEGER2long(st, &value);
/* Simple case: the integer size is small */
if(ret == 0) {
const asn_INTEGER_enum_map_t *el;
size_t scrsize;
char *scr;
el = (value >= 0 || !specs || !specs->field_unsigned)
? INTEGER_map_value2enum(specs, value) : 0;
if(el) {
scrsize = el->enum_len + 32;
scr = (char *)alloca(scrsize);
if(plainOrXER == 0)
ret = snprintf(scr, scrsize,
"%ld (%s)", value, el->enum_name);
else
ret = snprintf(scr, scrsize,
"<%s/>", el->enum_name);
} else if(plainOrXER && specs && specs->strict_enumeration) {
ASN_DEBUG("ASN.1 forbids dealing with "
"unknown value of ENUMERATED type");
errno = EPERM;
return -1;
} else {
scrsize = sizeof(scratch);
scr = scratch;
ret = snprintf(scr, scrsize,
(specs && specs->field_unsigned)
?"%lu":"%ld", value);
}
assert(ret > 0 && (size_t)ret < scrsize);
return (cb(scr, ret, app_key) < 0) ? -1 : ret;
} else if(plainOrXER && specs && specs->strict_enumeration) {
/*
* Here and earlier, we cannot encode the ENUMERATED values
* if there is no corresponding identifier.
*/
ASN_DEBUG("ASN.1 forbids dealing with "
"unknown value of ENUMERATED type");
errno = EPERM;
return -1;
}
/* Output in the long xx:yy:zz... format */
/* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */
for(p = scratch; buf < buf_end; buf++) {
const char * const h2c = "0123456789ABCDEF";
if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {
/* Flush buffer */
if(cb(scratch, p - scratch, app_key) < 0)
return -1;
wrote += p - scratch;
p = scratch;
}
*p++ = h2c[*buf >> 4];
*p++ = h2c[*buf & 0x0F];
*p++ = 0x3a; /* ":" */
}
if(p != scratch)
p--; /* Remove the last ":" */
wrote += p - scratch;
return (cb(scratch, p - scratch, app_key) < 0) ? -1 : wrote;
}
/*
* INTEGER specific human-readable output.
*/
int
INTEGER_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
const INTEGER_t *st = (const INTEGER_t *)sptr;
ssize_t ret;
(void)td;
(void)ilevel;
if(!st || !st->buf)
ret = cb("", 8, app_key);
else
ret = INTEGER__dump(td, st, cb, app_key, 0);
return (ret < 0) ? -1 : 0;
}
struct e2v_key {
const char *start;
const char *stop;
const asn_INTEGER_enum_map_t *vemap;
const unsigned int *evmap;
};
static int
INTEGER__compar_enum2value(const void *kp, const void *am) {
const struct e2v_key *key = (const struct e2v_key *)kp;
const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
const char *ptr, *end, *name;
/* Remap the element (sort by different criterion) */
el = key->vemap + key->evmap[el - key->vemap];
/* Compare strings */
for(ptr = key->start, end = key->stop, name = el->enum_name;
ptr < end; ptr++, name++) {
if(*ptr != *name)
return *(const unsigned char *)ptr
- *(const unsigned char *)name;
}
return name[0] ? -1 : 0;
}
static const asn_INTEGER_enum_map_t *
INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop) {
const asn_INTEGER_enum_map_t *el_found;
int count = specs ? specs->map_count : 0;
struct e2v_key key;
const char *lp;
if(!count) return NULL;
/* Guaranteed: assert(lstart < lstop); */
/* Figure out the tag name */
for(lstart++, lp = lstart; lp < lstop; lp++) {
switch(*lp) {
case 9: case 10: case 11: case 12: case 13: case 32: /* WSP */
case 0x2f: /* '/' */ case 0x3e: /* '>' */
break;
default:
continue;
}
break;
}
if(lp == lstop) return NULL; /* No tag found */
lstop = lp;
key.start = lstart;
key.stop = lstop;
key.vemap = specs->value2enum;
key.evmap = specs->enum2value;
el_found = (asn_INTEGER_enum_map_t *)bsearch(&key,
specs->value2enum, count, sizeof(specs->value2enum[0]),
INTEGER__compar_enum2value);
if(el_found) {
/* Remap enum2value into value2enum */
el_found = key.vemap + key.evmap[el_found - key.vemap];
}
return el_found;
}
static int
INTEGER__compar_value2enum(const void *kp, const void *am) {
long a = *(const long *)kp;
const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
long b = el->nat_value;
if(a < b) return -1;
else if(a == b) return 0;
else return 1;
}
const asn_INTEGER_enum_map_t *
INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value) {
int count = specs ? specs->map_count : 0;
if(!count) return 0;
return (asn_INTEGER_enum_map_t *)bsearch(&value, specs->value2enum,
count, sizeof(specs->value2enum[0]),
INTEGER__compar_value2enum);
}
static int
INTEGER_st_prealloc(INTEGER_t *st, int min_size) {
void *p = MALLOC(min_size + 1);
if(p) {
void *b = st->buf;
st->size = 0;
st->buf = p;
FREEMEM(b);
return 0;
} else {
return -1;
}
}
/*
* Decode the chunk of XML text encoding INTEGER.
*/
static enum xer_pbd_rval
INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
INTEGER_t *st = (INTEGER_t *)sptr;
long dec_value;
long hex_value = 0;
const char *lp;
const char *lstart = (const char *)chunk_buf;
const char *lstop = lstart + chunk_size;
enum {
ST_LEADSPACE,
ST_SKIPSPHEX,
ST_WAITDIGITS,
ST_DIGITS,
ST_DIGITS_TRAILSPACE,
ST_HEXDIGIT1,
ST_HEXDIGIT2,
ST_HEXDIGITS_TRAILSPACE,
ST_HEXCOLON,
ST_END_ENUM,
ST_UNEXPECTED
} state = ST_LEADSPACE;
const char *dec_value_start = 0; /* INVARIANT: always !0 in ST_DIGITS */
const char *dec_value_end = 0;
if(chunk_size)
ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x",
(long)chunk_size, *lstart, lstop[-1]);
if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
return XPBD_SYSTEM_FAILURE;
/*
* We may have received a tag here. It will be processed inline.
* Use strtoul()-like code and serialize the result.
*/
for(lp = lstart; lp < lstop; lp++) {
int lv = *lp;
switch(lv) {
case 0x09: case 0x0a: case 0x0d: case 0x20:
switch(state) {
case ST_LEADSPACE:
case ST_DIGITS_TRAILSPACE:
case ST_HEXDIGITS_TRAILSPACE:
case ST_SKIPSPHEX:
continue;
case ST_DIGITS:
dec_value_end = lp;
state = ST_DIGITS_TRAILSPACE;
continue;
case ST_HEXCOLON:
state = ST_HEXDIGITS_TRAILSPACE;
continue;
default:
break;
}
break;
case 0x2d: /* '-' */
if(state == ST_LEADSPACE) {
dec_value = 0;
dec_value_start = lp;
state = ST_WAITDIGITS;
continue;
}
break;
case 0x2b: /* '+' */
if(state == ST_LEADSPACE) {
dec_value = 0;
dec_value_start = lp;
state = ST_WAITDIGITS;
continue;
}
break;
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
switch(state) {
case ST_DIGITS: continue;
case ST_SKIPSPHEX: /* Fall through */
case ST_HEXDIGIT1:
hex_value = (lv - 0x30) << 4;
state = ST_HEXDIGIT2;
continue;
case ST_HEXDIGIT2:
hex_value += (lv - 0x30);
state = ST_HEXCOLON;
st->buf[st->size++] = (uint8_t)hex_value;
continue;
case ST_HEXCOLON:
return XPBD_BROKEN_ENCODING;
case ST_LEADSPACE:
dec_value = 0;
dec_value_start = lp;
/* FALL THROUGH */
case ST_WAITDIGITS:
state = ST_DIGITS;
continue;
default:
break;
}
break;
case 0x3c: /* '<', start of XML encoded enumeration */
if(state == ST_LEADSPACE) {
const asn_INTEGER_enum_map_t *el;
el = INTEGER_map_enum2value(
(asn_INTEGER_specifics_t *)
td->specifics, lstart, lstop);
if(el) {
ASN_DEBUG("Found \"%s\" => %ld",
el->enum_name, el->nat_value);
dec_value = el->nat_value;
state = ST_END_ENUM;
lp = lstop - 1;
continue;
}
ASN_DEBUG("Unknown identifier for INTEGER");
}
return XPBD_BROKEN_ENCODING;
case 0x3a: /* ':' */
if(state == ST_HEXCOLON) {
/* This colon is expected */
state = ST_HEXDIGIT1;
continue;
} else if(state == ST_DIGITS) {
/* The colon here means that we have
* decoded the first two hexadecimal
* places as a decimal value.
* Switch decoding mode. */
ASN_DEBUG("INTEGER re-evaluate as hex form");
state = ST_SKIPSPHEX;
dec_value_start = 0;
lp = lstart - 1;
continue;
} else {
ASN_DEBUG("state %d at %ld", state, (long)(lp - lstart));
break;
}
/* [A-Fa-f] */
case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:
case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:
switch(state) {
case ST_SKIPSPHEX:
case ST_LEADSPACE: /* Fall through */
case ST_HEXDIGIT1:
hex_value = lv - ((lv < 0x61) ? 0x41 : 0x61);
hex_value += 10;
hex_value <<= 4;
state = ST_HEXDIGIT2;
continue;
case ST_HEXDIGIT2:
hex_value += lv - ((lv < 0x61) ? 0x41 : 0x61);
hex_value += 10;
st->buf[st->size++] = (uint8_t)hex_value;
state = ST_HEXCOLON;
continue;
case ST_DIGITS:
ASN_DEBUG("INTEGER re-evaluate as hex form");
state = ST_SKIPSPHEX;
dec_value_start = 0;
lp = lstart - 1;
continue;
default:
break;
}
break;
}
/* Found extra non-numeric stuff */
ASN_DEBUG("INTEGER :: Found non-numeric 0x%2x at %ld",
lv, (long)(lp - lstart));
state = ST_UNEXPECTED;
break;
}
switch(state) {
case ST_END_ENUM:
/* Got a complete and valid enumeration encoded as a tag. */
break;
case ST_DIGITS:
dec_value_end = lstop;
/* FALL THROUGH */
case ST_DIGITS_TRAILSPACE:
/* The last symbol encountered was a digit. */
switch(asn_strtol_lim(dec_value_start, &dec_value_end, &dec_value)) {
case ASN_STRTOL_OK:
break;
case ASN_STRTOL_ERROR_RANGE:
return XPBD_DECODER_LIMIT;
case ASN_STRTOL_ERROR_INVAL:
case ASN_STRTOL_EXPECT_MORE:
case ASN_STRTOL_EXTRA_DATA:
return XPBD_BROKEN_ENCODING;
}
break;
case ST_HEXCOLON:
case ST_HEXDIGITS_TRAILSPACE:
st->buf[st->size] = 0; /* Just in case termination */
return XPBD_BODY_CONSUMED;
case ST_HEXDIGIT1:
case ST_HEXDIGIT2:
case ST_SKIPSPHEX:
return XPBD_BROKEN_ENCODING;
case ST_LEADSPACE:
/* Content not found */
return XPBD_NOT_BODY_IGNORE;
case ST_WAITDIGITS:
case ST_UNEXPECTED:
ASN_DEBUG("INTEGER: No useful digits (state %d)", state);
return XPBD_BROKEN_ENCODING; /* No digits */
}
/*
* Convert the result of parsing of enumeration or a straight
* decimal value into a BER representation.
*/
if(asn_long2INTEGER(st, dec_value))
return XPBD_SYSTEM_FAILURE;
return XPBD_BODY_CONSUMED;
}
asn_dec_rval_t
INTEGER_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
const void *buf_ptr, size_t size) {
return xer_decode_primitive(opt_codec_ctx, td,
sptr, sizeof(INTEGER_t), opt_mname,
buf_ptr, size, INTEGER__xer_body_decode);
}
asn_enc_rval_t
INTEGER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
const INTEGER_t *st = (const INTEGER_t *)sptr;
asn_enc_rval_t er;
(void)ilevel;
(void)flags;
if(!st || !st->buf)
ASN__ENCODE_FAILED;
er.encoded = INTEGER__dump(td, st, cb, app_key, 1);
if(er.encoded < 0) ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
#ifndef ASN_DISABLE_PER_SUPPORT
asn_dec_rval_t
INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval = { RC_OK, 0 };
INTEGER_t *st = (INTEGER_t *)*sptr;
asn_per_constraint_t *ct;
int repeat;
(void)opt_codec_ctx;
if(!st) {
st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
if(!st) ASN__DECODE_FAILED;
}
if(!constraints) constraints = td->per_constraints;
ct = constraints ? &constraints->value : 0;
if(ct && ct->flags & APC_EXTENSIBLE) {
int inext = per_get_few_bits(pd, 1);
if(inext < 0) ASN__DECODE_STARVED;
if(inext) ct = 0;
}
FREEMEM(st->buf);
st->buf = 0;
st->size = 0;
if(ct) {
if(ct->flags & APC_SEMI_CONSTRAINED) {
st->buf = (uint8_t *)CALLOC(1, 2);
if(!st->buf) ASN__DECODE_FAILED;
st->size = 1;
} else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
size_t size = (ct->range_bits + 7) >> 3;
st->buf = (uint8_t *)MALLOC(1 + size + 1);
if(!st->buf) ASN__DECODE_FAILED;
st->size = size;
}
}
/* X.691-2008/11, #13.2.2, constrained whole number */
if(ct && ct->flags != APC_UNCONSTRAINED) {
/* #11.5.6 */
ASN_DEBUG("Integer with range %d bits", ct->range_bits);
if(ct->range_bits >= 0) {
if((size_t)ct->range_bits > 8 * sizeof(unsigned long))
ASN__DECODE_FAILED;
if(specs && specs->field_unsigned) {
unsigned long uvalue;
if(uper_get_constrained_whole_number(pd,
&uvalue, ct->range_bits))
ASN__DECODE_STARVED;
ASN_DEBUG("Got value %lu + low %ld",
uvalue, ct->lower_bound);
uvalue += ct->lower_bound;
if(asn_ulong2INTEGER(st, uvalue))
ASN__DECODE_FAILED;
} else {
unsigned long svalue;
if(uper_get_constrained_whole_number(pd,
&svalue, ct->range_bits))
ASN__DECODE_STARVED;
ASN_DEBUG("Got value %ld + low %ld",
svalue, ct->lower_bound);
svalue += ct->lower_bound;
if(asn_long2INTEGER(st, svalue))
ASN__DECODE_FAILED;
}
return rval;
}
} else {
ASN_DEBUG("Decoding unconstrained integer %s", td->name);
}
/* X.691, #12.2.3, #12.2.4 */
do {
ssize_t len;
void *p;
int ret;
/* Get the PER length */
len = uper_get_length(pd, -1, &repeat);
if(len < 0) ASN__DECODE_STARVED;
p = REALLOC(st->buf, st->size + len + 1);
if(!p) ASN__DECODE_FAILED;
st->buf = (uint8_t *)p;
ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
if(ret < 0) ASN__DECODE_STARVED;
st->size += len;
} while(repeat);
st->buf[st->size] = 0; /* JIC */
/* #12.2.3 */
if(ct && ct->lower_bound) {
/*
* TODO: replace by in-place arithmetics.
*/
long value;
if(asn_INTEGER2long(st, &value))
ASN__DECODE_FAILED;
if(asn_long2INTEGER(st, value + ct->lower_bound))
ASN__DECODE_FAILED;
}
return rval;
}
asn_enc_rval_t
INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er;
INTEGER_t *st = (INTEGER_t *)sptr;
const uint8_t *buf;
const uint8_t *end;
asn_per_constraint_t *ct;
long value = 0;
unsigned long v = 0;
if(!st || st->size == 0) ASN__ENCODE_FAILED;
if(!constraints) constraints = td->per_constraints;
ct = constraints ? &constraints->value : 0;
er.encoded = 0;
if(ct) {
int inext = 0;
if(specs && specs->field_unsigned) {
unsigned long uval;
if(asn_INTEGER2ulong(st, &uval))
ASN__ENCODE_FAILED;
/* Check proper range */
if(ct->flags & APC_SEMI_CONSTRAINED) {
if(uval < (unsigned long)ct->lower_bound)
inext = 1;
} else if(ct->range_bits >= 0) {
if(uval < (unsigned long)ct->lower_bound
|| uval > (unsigned long)ct->upper_bound)
inext = 1;
}
ASN_DEBUG("Value %lu (%02x/%d) lb %lu ub %lu %s",
uval, st->buf[0], st->size,
ct->lower_bound, ct->upper_bound,
inext ? "ext" : "fix");
value = uval;
} else {
if(asn_INTEGER2long(st, &value))
ASN__ENCODE_FAILED;
/* Check proper range */
if(ct->flags & APC_SEMI_CONSTRAINED) {
if(value < ct->lower_bound)
inext = 1;
} else if(ct->range_bits >= 0) {
if(value < ct->lower_bound
|| value > ct->upper_bound)
inext = 1;
}
ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s",
value, st->buf[0], st->size,
ct->lower_bound, ct->upper_bound,
inext ? "ext" : "fix");
}
if(ct->flags & APC_EXTENSIBLE) {
if(per_put_few_bits(po, inext, 1))
ASN__ENCODE_FAILED;
if(inext) ct = 0;
} else if(inext) {
ASN__ENCODE_FAILED;
}
}
/* X.691-11/2008, #13.2.2, test if constrained whole number */
if(ct && ct->range_bits >= 0) {
/* #11.5.6 -> #11.3 */
ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits",
value, value - ct->lower_bound, ct->range_bits);
v = value - ct->lower_bound;
if(uper_put_constrained_whole_number_u(po, v, ct->range_bits))
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
if(ct && ct->lower_bound) {
ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
/* TODO: adjust lower bound */
ASN__ENCODE_FAILED;
}
for(buf = st->buf, end = st->buf + st->size; buf < end;) {
ssize_t mayEncode = uper_put_length(po, end - buf);
if(mayEncode < 0)
ASN__ENCODE_FAILED;
if(per_put_many_bits(po, buf, 8 * mayEncode))
ASN__ENCODE_FAILED;
buf += mayEncode;
}
ASN__ENCODED_OK(er);
}
#endif /* ASN_DISABLE_PER_SUPPORT */
int
asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
uint8_t *b, *end;
size_t size;
long l;
/* Sanity checking */
if(!iptr || !iptr->buf || !lptr) {
errno = EINVAL;
return -1;
}
/* Cache the begin/end of the buffer */
b = iptr->buf; /* Start of the INTEGER buffer */
size = iptr->size;
end = b + size; /* Where to stop */
if(size > sizeof(long)) {
uint8_t *end1 = end - 1;
/*
* Slightly more advanced processing,
* able to >sizeof(long) bytes,
* when the actual value is small
* (0x0000000000abcdef would yield a fine 0x00abcdef)
*/
/* Skip out the insignificant leading bytes */
for(; b < end1; b++) {
switch(*b) {
case 0x00: if((b[1] & 0x80) == 0) continue; break;
case 0xff: if((b[1] & 0x80) != 0) continue; break;
}
break;
}
size = end - b;
if(size > sizeof(long)) {
/* Still cannot fit the long */
errno = ERANGE;
return -1;
}
}
/* Shortcut processing of a corner case */
if(end == b) {
*lptr = 0;
return 0;
}
/* Perform the sign initialization */
/* Actually l = -(*b >> 7); gains nothing, yet unreadable! */
if((*b >> 7)) l = -1; else l = 0;
/* Conversion engine */
for(; b < end; b++)
l = (l << 8) | *b;
*lptr = l;
return 0;
}
int
asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *lptr) {
uint8_t *b, *end;
unsigned long l;
size_t size;
if(!iptr || !iptr->buf || !lptr) {
errno = EINVAL;
return -1;
}
b = iptr->buf;
size = iptr->size;
end = b + size;
/* If all extra leading bytes are zeroes, ignore them */
for(; size > sizeof(unsigned long); b++, size--) {
if(*b) {
/* Value won't fit unsigned long */
errno = ERANGE;
return -1;
}
}
/* Conversion engine */
for(l = 0; b < end; b++)
l = (l << 8) | *b;
*lptr = l;
return 0;
}
int
asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
uint8_t *buf;
uint8_t *end;
uint8_t *b;
int shr;
if(value <= LONG_MAX)
return asn_long2INTEGER(st, value);
buf = (uint8_t *)MALLOC(1 + sizeof(value));
if(!buf) return -1;
end = buf + (sizeof(value) + 1);
buf[0] = 0;
for(b = buf + 1, shr = (sizeof(long)-1)*8; b < end; shr -= 8, b++)
*b = (uint8_t)(value >> shr);
if(st->buf) FREEMEM(st->buf);
st->buf = buf;
st->size = 1 + sizeof(value);
return 0;
}
int
asn_long2INTEGER(INTEGER_t *st, long value) {
uint8_t *buf, *bp;
uint8_t *p;
uint8_t *pstart;
uint8_t *pend1;
int littleEndian = 1; /* Run-time detection */
int add;
if(!st) {
errno = EINVAL;
return -1;
}
buf = (uint8_t *)MALLOC(sizeof(value));
if(!buf) return -1;
if(*(char *)&littleEndian) {
pstart = (uint8_t *)&value + sizeof(value) - 1;
pend1 = (uint8_t *)&value;
add = -1;
} else {
pstart = (uint8_t *)&value;
pend1 = pstart + sizeof(value) - 1;
add = 1;
}
/*
* If the contents octet consists of more than one octet,
* then bits of the first octet and bit 8 of the second octet:
* a) shall not all be ones; and
* b) shall not all be zero.
*/
for(p = pstart; p != pend1; p += add) {
switch(*p) {
case 0x00: if((*(p+add) & 0x80) == 0)
continue;
break;
case 0xff: if((*(p+add) & 0x80))
continue;
break;
}
break;
}
/* Copy the integer body */
for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add)
*bp++ = *p;
if(st->buf) FREEMEM(st->buf);
st->buf = buf;
st->size = bp - buf;
return 0;
}
/*
* This function is going to be DEPRECATED soon.
*/
enum asn_strtol_result_e
asn_strtol(const char *str, const char *end, long *lp) {
const char *endp = end;
switch(asn_strtol_lim(str, &endp, lp)) {
case ASN_STRTOL_ERROR_RANGE:
return ASN_STRTOL_ERROR_RANGE;
case ASN_STRTOL_ERROR_INVAL:
return ASN_STRTOL_ERROR_INVAL;
case ASN_STRTOL_EXPECT_MORE:
return ASN_STRTOL_ERROR_INVAL; /* Retain old behavior */
case ASN_STRTOL_OK:
return ASN_STRTOL_OK;
case ASN_STRTOL_EXTRA_DATA:
return ASN_STRTOL_ERROR_INVAL; /* Retain old behavior */
}
return ASN_STRTOL_ERROR_INVAL; /* Retain old behavior */
}
/*
* Parse the number in the given string until the given *end position,
* returning the position after the last parsed character back using the
* same (*end) pointer.
* WARNING: This behavior is different from the standard strtol(3).
*/
enum asn_strtol_result_e
asn_strtol_lim(const char *str, const char **end, long *lp) {
int sign = 1;
long l;
const long upper_boundary = LONG_MAX / 10;
long last_digit_max = LONG_MAX % 10;
if(str >= *end) return ASN_STRTOL_ERROR_INVAL;
switch(*str) {
case '-':
last_digit_max++;
sign = -1;
/* FALL THROUGH */
case '+':
str++;
if(str >= *end) {
*end = str;
return ASN_STRTOL_EXPECT_MORE;
}
}
for(l = 0; str < (*end); str++) {
switch(*str) {
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: {
int d = *str - '0';
if(l < upper_boundary) {
l = l * 10 + d;
} else if(l == upper_boundary) {
if(d <= last_digit_max) {
if(sign > 0) {
l = l * 10 + d;
} else {
sign = 1;
l = -l * 10 - d;
}
} else {
*end = str;
return ASN_STRTOL_ERROR_RANGE;
}
} else {
*end = str;
return ASN_STRTOL_ERROR_RANGE;
}
}
continue;
default:
*end = str;
*lp = sign * l;
return ASN_STRTOL_EXTRA_DATA;
}
}
*end = str;
*lp = sign * l;
return ASN_STRTOL_OK;
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/INTEGER.h 0000664 0000000 0000000 00000005635 15245442746 0025606 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2005 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _INTEGER_H_
#define _INTEGER_H_
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
typedef ASN__PRIMITIVE_TYPE_t INTEGER_t;
extern asn_TYPE_descriptor_t asn_DEF_INTEGER;
/* Map with to integer value association */
typedef struct asn_INTEGER_enum_map_s {
long nat_value; /* associated native integer value */
size_t enum_len; /* strlen("tag") */
const char *enum_name; /* "tag" */
} asn_INTEGER_enum_map_t;
/* This type describes an enumeration for INTEGER and ENUMERATED types */
typedef const struct asn_INTEGER_specifics_s {
const asn_INTEGER_enum_map_t *value2enum; /* N -> "tag"; sorted by N */
const unsigned int *enum2value; /* "tag" => N; sorted by tag */
int map_count; /* Elements in either map */
int extension; /* This map is extensible */
int strict_enumeration; /* Enumeration set is fixed */
int field_width; /* Size of native integer */
int field_unsigned; /* Signed=0, unsigned=1 */
} asn_INTEGER_specifics_t;
asn_struct_print_f INTEGER_print;
ber_type_decoder_f INTEGER_decode_ber;
der_type_encoder_f INTEGER_encode_der;
xer_type_decoder_f INTEGER_decode_xer;
xer_type_encoder_f INTEGER_encode_xer;
per_type_decoder_f INTEGER_decode_uper;
per_type_encoder_f INTEGER_encode_uper;
/***********************************
* Some handy conversion routines. *
***********************************/
/*
* Returns 0 if it was possible to convert, -1 otherwise.
* -1/EINVAL: Mandatory argument missing
* -1/ERANGE: Value encoded is out of range for long representation
* -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()).
*/
int asn_INTEGER2long(const INTEGER_t *i, long *l);
int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l);
int asn_long2INTEGER(INTEGER_t *i, long l);
int asn_ulong2INTEGER(INTEGER_t *i, unsigned long l);
/* A a reified version of strtol(3) with nicer error reporting. */
enum asn_strtol_result_e {
ASN_STRTOL_ERROR_RANGE = -3, /* Input outside of numeric range for long type */
ASN_STRTOL_ERROR_INVAL = -2, /* Invalid data encountered (e.g., "+-") */
ASN_STRTOL_EXPECT_MORE = -1, /* More data expected (e.g. "+") */
ASN_STRTOL_OK = 0, /* Conversion succeded, number ends at (*end) */
ASN_STRTOL_EXTRA_DATA = 1 /* Conversion succeded, but the string has extra stuff */
};
enum asn_strtol_result_e asn_strtol_lim(const char *str, const char **end, long *l);
/* The asn_strtol is going to be DEPRECATED soon */
enum asn_strtol_result_e asn_strtol(const char *str, const char *end, long *l);
/*
* Convert the integer value into the corresponding enumeration map entry.
*/
const asn_INTEGER_enum_map_t *INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value);
#ifdef __cplusplus
}
#endif
#endif /* _INTEGER_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/NativeEnumerated.c 0000664 0000000 0000000 00000013442 15245442746 0027737 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2004, 2007 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
* Read the NativeInteger.h for the explanation wrt. differences between
* INTEGER and NativeInteger.
* Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
* implementation deals with the standard (machine-specific) representation
* of them instead of using the platform-independent buffer.
*/
#include
#include
/*
* NativeEnumerated basic type description.
*/
static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
};
asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
"ENUMERATED", /* The ASN.1 type is still ENUMERATED */
"ENUMERATED",
NativeInteger_free,
NativeInteger_print,
asn_generic_no_constraint,
NativeInteger_decode_ber,
NativeInteger_encode_der,
NativeInteger_decode_xer,
NativeEnumerated_encode_xer,
NativeEnumerated_decode_uper,
NativeEnumerated_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeEnumerated_tags,
sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
asn_DEF_NativeEnumerated_tags, /* Same as above */
sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
0, /* No PER visible constraints */
0, 0, /* No members */
0 /* No specifics */
};
asn_enc_rval_t
NativeEnumerated_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er;
const long *native = (const long *)sptr;
const asn_INTEGER_enum_map_t *el;
(void)ilevel;
(void)flags;
if(!native) ASN__ENCODE_FAILED;
el = INTEGER_map_value2enum(specs, *native);
if(el) {
size_t srcsize = el->enum_len + 5;
char *src = (char *)alloca(srcsize);
er.encoded = snprintf(src, srcsize, "<%s/>", el->enum_name);
assert(er.encoded > 0 && (size_t)er.encoded < srcsize);
if(cb(src, er.encoded, app_key) < 0) ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
} else {
ASN_DEBUG("ASN.1 forbids dealing with "
"unknown value of ENUMERATED type");
ASN__ENCODE_FAILED;
}
}
asn_dec_rval_t
NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
void **sptr, asn_per_data_t *pd) {
asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval = { RC_OK, 0 };
long *native = (long *)*sptr;
asn_per_constraint_t *ct;
long value;
(void)opt_codec_ctx;
if(constraints) ct = &constraints->value;
else if(td->per_constraints) ct = &td->per_constraints->value;
else ASN__DECODE_FAILED; /* Mandatory! */
if(!specs) ASN__DECODE_FAILED;
if(!native) {
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
if(!native) ASN__DECODE_FAILED;
}
ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
if(ct->flags & APC_EXTENSIBLE) {
int inext = per_get_few_bits(pd, 1);
if(inext < 0) ASN__DECODE_STARVED;
if(inext) ct = 0;
}
if(ct && ct->range_bits >= 0) {
value = per_get_few_bits(pd, ct->range_bits);
if(value < 0) ASN__DECODE_STARVED;
if(value >= (specs->extension
? specs->extension - 1 : specs->map_count))
ASN__DECODE_FAILED;
} else {
if(!specs->extension)
ASN__DECODE_FAILED;
/*
* X.691, #10.6: normally small non-negative whole number;
*/
value = uper_get_nsnnwn(pd);
if(value < 0) ASN__DECODE_STARVED;
value += specs->extension - 1;
if(value >= specs->map_count)
ASN__DECODE_FAILED;
}
*native = specs->value2enum[value].nat_value;
ASN_DEBUG("Decoded %s = %ld", td->name, *native);
return rval;
}
static int
NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
const asn_INTEGER_enum_map_t *a = ap;
const asn_INTEGER_enum_map_t *b = bp;
if(a->nat_value == b->nat_value)
return 0;
if(a->nat_value < b->nat_value)
return -1;
return 1;
}
asn_enc_rval_t
NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er;
long native, value;
asn_per_constraint_t *ct;
int inext = 0;
asn_INTEGER_enum_map_t key;
const asn_INTEGER_enum_map_t *kf;
if(!sptr) ASN__ENCODE_FAILED;
if(!specs) ASN__ENCODE_FAILED;
if(constraints) ct = &constraints->value;
else if(td->per_constraints) ct = &td->per_constraints->value;
else ASN__ENCODE_FAILED; /* Mandatory! */
ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
er.encoded = 0;
native = *(long *)sptr;
if(native < 0) ASN__ENCODE_FAILED;
key.nat_value = native;
kf = bsearch(&key, specs->value2enum, specs->map_count,
sizeof(key), NativeEnumerated__compar_value2enum);
if(!kf) {
ASN_DEBUG("No element corresponds to %ld", native);
ASN__ENCODE_FAILED;
}
value = kf - specs->value2enum;
if(ct->range_bits >= 0) {
int cmpWith = specs->extension
? specs->extension - 1 : specs->map_count;
if(value >= cmpWith)
inext = 1;
}
if(ct->flags & APC_EXTENSIBLE) {
if(per_put_few_bits(po, inext, 1))
ASN__ENCODE_FAILED;
if(inext) ct = 0;
} else if(inext) {
ASN__ENCODE_FAILED;
}
if(ct && ct->range_bits >= 0) {
if(per_put_few_bits(po, value, ct->range_bits))
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
if(!specs->extension)
ASN__ENCODE_FAILED;
/*
* X.691, #10.6: normally small non-negative whole number;
*/
ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
value, specs->extension, inext,
value - (inext ? (specs->extension - 1) : 0));
if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/NativeEnumerated.h 0000664 0000000 0000000 00000001601 15245442746 0027736 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2004, 2005, 2006 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
* This type differs from the standard ENUMERATED in that it is modelled using
* the fixed machine type (long, int, short), so it can hold only values of
* limited length. There is no type (i.e., NativeEnumerated_t, any integer type
* will do).
* This type may be used when integer range is limited by subtype constraints.
*/
#ifndef _NativeEnumerated_H_
#define _NativeEnumerated_H_
#include
#ifdef __cplusplus
extern "C" {
#endif
extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
xer_type_encoder_f NativeEnumerated_encode_xer;
per_type_decoder_f NativeEnumerated_decode_uper;
per_type_encoder_f NativeEnumerated_encode_uper;
#ifdef __cplusplus
}
#endif
#endif /* _NativeEnumerated_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/NativeInteger.c 0000664 0000000 0000000 00000021113 15245442746 0027235 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2004, 2005, 2006 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
* Read the NativeInteger.h for the explanation wrt. differences between
* INTEGER and NativeInteger.
* Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
* implementation deals with the standard (machine-specific) representation
* of them instead of using the platform-independent buffer.
*/
#include
#include
/*
* NativeInteger basic type description.
*/
static const ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
};
asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
"INTEGER", /* The ASN.1 type is still INTEGER */
"INTEGER",
NativeInteger_free,
NativeInteger_print,
asn_generic_no_constraint,
NativeInteger_decode_ber,
NativeInteger_encode_der,
NativeInteger_decode_xer,
NativeInteger_encode_xer,
NativeInteger_decode_uper, /* Unaligned PER decoder */
NativeInteger_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeInteger_tags,
sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
asn_DEF_NativeInteger_tags, /* Same as above */
sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
0, /* No PER visible constraints */
0, 0, /* No members */
0 /* No specifics */
};
/*
* Decode INTEGER type.
*/
asn_dec_rval_t
NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td,
void **nint_ptr, const void *buf_ptr, size_t size, int tag_mode) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
long *native = (long *)*nint_ptr;
asn_dec_rval_t rval;
ber_tlv_len_t length;
/*
* If the structure is not there, allocate it.
*/
if(native == NULL) {
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
if(native == NULL) {
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
}
}
ASN_DEBUG("Decoding %s as INTEGER (tm=%d)",
td->name, tag_mode);
/*
* Check tags.
*/
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
tag_mode, 0, &length, 0);
if(rval.code != RC_OK)
return rval;
ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
/*
* Make sure we have this length.
*/
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
size -= rval.consumed;
if(length > (ber_tlv_len_t)size) {
rval.code = RC_WMORE;
rval.consumed = 0;
return rval;
}
/*
* ASN.1 encoded INTEGER: buf_ptr, length
* Fill the native, at the same time checking for overflow.
* If overflow occured, return with RC_FAIL.
*/
{
INTEGER_t tmp;
union {
const void *constbuf;
void *nonconstbuf;
} unconst_buf;
long l;
unconst_buf.constbuf = buf_ptr;
tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
tmp.size = length;
if((specs&&specs->field_unsigned)
? asn_INTEGER2ulong(&tmp, (unsigned long *)&l) /* sic */
: asn_INTEGER2long(&tmp, &l)) {
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
}
*native = l;
}
rval.code = RC_OK;
rval.consumed += length;
ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)",
(long)rval.consumed, (long)length, td->name, (long)*native);
return rval;
}
/*
* Encode the NativeInteger using the standard INTEGER type DER encoder.
*/
asn_enc_rval_t
NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr,
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
unsigned long native = *(unsigned long *)ptr; /* Disable sign ext. */
asn_enc_rval_t erval;
INTEGER_t tmp;
#ifdef WORDS_BIGENDIAN /* Opportunistic optimization */
tmp.buf = (uint8_t *)&native;
tmp.size = sizeof(native);
#else /* Works even if WORDS_BIGENDIAN is not set where should've been */
uint8_t buf[sizeof(native)];
uint8_t *p;
/* Prepare a fake INTEGER */
for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8)
*p = (uint8_t)native;
tmp.buf = buf;
tmp.size = sizeof(buf);
#endif /* WORDS_BIGENDIAN */
/* Encode fake INTEGER */
erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key);
if(erval.encoded == -1) {
assert(erval.structure_ptr == &tmp);
erval.structure_ptr = ptr;
}
return erval;
}
/*
* Decode the chunk of XML text encoding INTEGER.
*/
asn_dec_rval_t
NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
const void *buf_ptr, size_t size) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval;
INTEGER_t st;
void *st_ptr = (void *)&st;
long *native = (long *)*sptr;
if(!native) {
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
if(!native) ASN__DECODE_FAILED;
}
memset(&st, 0, sizeof(st));
rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr,
opt_mname, buf_ptr, size);
if(rval.code == RC_OK) {
long l;
if((specs&&specs->field_unsigned)
? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */
: asn_INTEGER2long(&st, &l)) {
rval.code = RC_FAIL;
rval.consumed = 0;
} else {
*native = l;
}
} else {
/*
* Cannot restart from the middle;
* there is no place to save state in the native type.
* Request a continuation from the very beginning.
*/
rval.consumed = 0;
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
return rval;
}
asn_enc_rval_t
NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
char scratch[32]; /* Enough for 64-bit int */
asn_enc_rval_t er;
const long *native = (const long *)sptr;
(void)ilevel;
(void)flags;
if(!native) ASN__ENCODE_FAILED;
er.encoded = snprintf(scratch, sizeof(scratch),
(specs && specs->field_unsigned)
? "%lu" : "%ld", *native);
if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
|| cb(scratch, er.encoded, app_key) < 0)
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
asn_dec_rval_t
NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval;
long *native = (long *)*sptr;
INTEGER_t tmpint;
void *tmpintptr = &tmpint;
(void)opt_codec_ctx;
ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name);
if(!native) {
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
if(!native) ASN__DECODE_FAILED;
}
memset(&tmpint, 0, sizeof tmpint);
rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints,
&tmpintptr, pd);
if(rval.code == RC_OK) {
if((specs&&specs->field_unsigned)
? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
: asn_INTEGER2long(&tmpint, native))
rval.code = RC_FAIL;
else
ASN_DEBUG("NativeInteger %s got value %ld",
td->name, *native);
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
return rval;
}
asn_enc_rval_t
NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er;
long native;
INTEGER_t tmpint;
if(!sptr) ASN__ENCODE_FAILED;
native = *(long *)sptr;
ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native);
memset(&tmpint, 0, sizeof(tmpint));
if((specs&&specs->field_unsigned)
? asn_ulong2INTEGER(&tmpint, native)
: asn_long2INTEGER(&tmpint, native))
ASN__ENCODE_FAILED;
er = INTEGER_encode_uper(td, constraints, &tmpint, po);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
return er;
}
/*
* INTEGER specific human-readable output.
*/
int
NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
const long *native = (const long *)sptr;
char scratch[32]; /* Enough for 64-bit int */
int ret;
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(native) {
ret = snprintf(scratch, sizeof(scratch),
(specs && specs->field_unsigned)
? "%lu" : "%ld", *native);
assert(ret > 0 && (size_t)ret < sizeof(scratch));
return (cb(scratch, ret, app_key) < 0) ? -1 : 0;
} else {
return (cb("", 8, app_key) < 0) ? -1 : 0;
}
}
void
NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
if(!td || !ptr)
return;
ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)",
td->name, contents_only, ptr);
if(!contents_only) {
FREEMEM(ptr);
}
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/NativeInteger.h 0000664 0000000 0000000 00000002104 15245442746 0027241 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
* This type differs from the standard INTEGER in that it is modelled using
* the fixed machine type (long, int, short), so it can hold only values of
* limited length. There is no type (i.e., NativeInteger_t, any integer type
* will do).
* This type may be used when integer range is limited by subtype constraints.
*/
#ifndef _NativeInteger_H_
#define _NativeInteger_H_
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
extern asn_TYPE_descriptor_t asn_DEF_NativeInteger;
asn_struct_free_f NativeInteger_free;
asn_struct_print_f NativeInteger_print;
ber_type_decoder_f NativeInteger_decode_ber;
der_type_encoder_f NativeInteger_encode_der;
xer_type_decoder_f NativeInteger_decode_xer;
xer_type_encoder_f NativeInteger_encode_xer;
per_type_decoder_f NativeInteger_decode_uper;
per_type_encoder_f NativeInteger_encode_uper;
#ifdef __cplusplus
}
#endif
#endif /* _NativeInteger_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/OCTET_STRING.c 0000664 0000000 0000000 00000133313 15245442746 0026443 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include /* for .bits_unused member */
#include
/*
* OCTET STRING basic type description.
*/
static const ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
};
static const asn_OCTET_STRING_specifics_t asn_DEF_OCTET_STRING_specs = {
sizeof(OCTET_STRING_t),
offsetof(OCTET_STRING_t, _asn_ctx),
ASN_OSUBV_STR
};
static const asn_per_constraints_t asn_DEF_OCTET_STRING_constraints = {
{ APC_CONSTRAINED, 8, 8, 0, 255 },
{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
0, 0
};
asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
"OCTET STRING", /* Canonical name */
"OCTET_STRING", /* XML tag name */
OCTET_STRING_free,
OCTET_STRING_print, /* non-ascii stuff, generally */
asn_generic_no_constraint,
OCTET_STRING_decode_ber,
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Unaligned PER decoder */
OCTET_STRING_encode_uper, /* Unaligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_OCTET_STRING_tags,
sizeof(asn_DEF_OCTET_STRING_tags)
/ sizeof(asn_DEF_OCTET_STRING_tags[0]),
asn_DEF_OCTET_STRING_tags, /* Same as above */
sizeof(asn_DEF_OCTET_STRING_tags)
/ sizeof(asn_DEF_OCTET_STRING_tags[0]),
0, /* No PER visible constraints */
0, 0, /* No members */
&asn_DEF_OCTET_STRING_specs
};
#undef _CH_PHASE
#undef NEXT_PHASE
#undef PREV_PHASE
#define _CH_PHASE(ctx, inc) do { \
if(ctx->phase == 0) \
ctx->context = 0; \
ctx->phase += inc; \
} while(0)
#define NEXT_PHASE(ctx) _CH_PHASE(ctx, +1)
#define PREV_PHASE(ctx) _CH_PHASE(ctx, -1)
#undef ADVANCE
#define ADVANCE(num_bytes) do { \
size_t num = (num_bytes); \
buf_ptr = ((const char *)buf_ptr) + num; \
size -= num; \
consumed_myself += num; \
} while(0)
#undef RETURN
#define RETURN(_code) do { \
asn_dec_rval_t tmprval; \
tmprval.code = _code; \
tmprval.consumed = consumed_myself; \
return tmprval; \
} while(0)
#undef APPEND
#define APPEND(bufptr, bufsize) do { \
size_t _bs = (bufsize); /* Append size */ \
size_t _ns = ctx->context; /* Allocated now */ \
size_t _es = st->size + _bs; /* Expected size */ \
/* int is really a typeof(st->size): */ \
if((int)_es < 0) RETURN(RC_FAIL); \
if(_ns <= _es) { \
void *ptr; \
/* Be nice and round to the memory allocator */ \
do { _ns = _ns ? _ns << 1 : 16; } \
while(_ns <= _es); \
/* int is really a typeof(st->size): */ \
if((int)_ns < 0) RETURN(RC_FAIL); \
ptr = REALLOC(st->buf, _ns); \
if(ptr) { \
st->buf = (uint8_t *)ptr; \
ctx->context = _ns; \
} else { \
RETURN(RC_FAIL); \
} \
ASN_DEBUG("Reallocating into %ld", (long)_ns); \
} \
memcpy(st->buf + st->size, bufptr, _bs); \
/* Convenient nul-termination */ \
st->buf[_es] = '\0'; \
st->size = _es; \
} while(0)
/*
* The main reason why ASN.1 is still alive is that too much time and effort
* is necessary for learning it more or less adequately, thus creating a gut
* necessity to demonstrate that aquired skill everywhere afterwards.
* No, I am not going to explain what the following stuff is.
*/
struct _stack_el {
ber_tlv_len_t left; /* What's left to read (or -1) */
ber_tlv_len_t got; /* What was actually processed */
int cont_level; /* Depth of subcontainment */
int want_nulls; /* Want null "end of content" octets? */
int bits_chopped; /* Flag in BIT STRING mode */
ber_tlv_tag_t tag; /* For debugging purposes */
struct _stack_el *prev;
struct _stack_el *next;
};
struct _stack {
struct _stack_el *tail;
struct _stack_el *cur_ptr;
};
static struct _stack_el *
OS__add_stack_el(struct _stack *st) {
struct _stack_el *nel;
/*
* Reuse the old stack frame or allocate a new one.
*/
if(st->cur_ptr && st->cur_ptr->next) {
nel = st->cur_ptr->next;
nel->bits_chopped = 0;
nel->got = 0;
/* Retain the nel->cont_level, it's correct. */
} else {
nel = (struct _stack_el *)CALLOC(1, sizeof(struct _stack_el));
if(nel == NULL)
return NULL;
if(st->tail) {
/* Increase a subcontainment depth */
nel->cont_level = st->tail->cont_level + 1;
st->tail->next = nel;
}
nel->prev = st->tail;
st->tail = nel;
}
st->cur_ptr = nel;
return nel;
}
static struct _stack *
_new_stack() {
return (struct _stack *)CALLOC(1, sizeof(struct _stack));
}
/*
* Decode OCTET STRING type.
*/
asn_dec_rval_t
OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td,
void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
asn_OCTET_STRING_specifics_t *specs = td->specifics
? (asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_DEF_OCTET_STRING_specs;
BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
asn_dec_rval_t rval;
asn_struct_ctx_t *ctx;
ssize_t consumed_myself = 0;
struct _stack *stck; /* Expectations stack structure */
struct _stack_el *sel = 0; /* Stack element */
int tlv_constr;
enum asn_OS_Subvariant type_variant = specs->subvariant;
ASN_DEBUG("Decoding %s as %s (frame %ld)",
td->name,
(type_variant == ASN_OSUBV_STR) ?
"OCTET STRING" : "OS-SpecialCase",
(long)size);
/*
* Create the string if does not exist.
*/
if(st == NULL) {
st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
if(st == NULL) RETURN(RC_FAIL);
}
/* Restore parsing context */
ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
switch(ctx->phase) {
case 0:
/*
* Check tags.
*/
rval = ber_check_tags(opt_codec_ctx, td, ctx,
buf_ptr, size, tag_mode, -1,
&ctx->left, &tlv_constr);
if(rval.code != RC_OK)
return rval;
if(tlv_constr) {
/*
* Complex operation, requires stack of expectations.
*/
ctx->ptr = _new_stack();
if(ctx->ptr) {
stck = (struct _stack *)ctx->ptr;
} else {
RETURN(RC_FAIL);
}
} else {
/*
* Jump into stackless primitive decoding.
*/
_CH_PHASE(ctx, 3);
if(type_variant == ASN_OSUBV_ANY && tag_mode != 1)
APPEND(buf_ptr, rval.consumed);
ADVANCE(rval.consumed);
goto phase3;
}
NEXT_PHASE(ctx);
/* Fall through */
case 1:
phase1:
/*
* Fill the stack with expectations.
*/
stck = (struct _stack *)ctx->ptr;
sel = stck->cur_ptr;
do {
ber_tlv_tag_t tlv_tag;
ber_tlv_len_t tlv_len;
ber_tlv_tag_t expected_tag;
ssize_t tl, ll, tlvl;
/* This one works even if (sel->left == -1) */
ssize_t Left = ((!sel||(size_t)sel->left >= size)
?(ssize_t)size:sel->left);
ASN_DEBUG("%p, s->l=%ld, s->wn=%ld, s->g=%ld\n", sel,
(long)(sel?sel->left:0),
(long)(sel?sel->want_nulls:0),
(long)(sel?sel->got:0)
);
if(sel && sel->left <= 0 && sel->want_nulls == 0) {
if(sel->prev) {
struct _stack_el *prev = sel->prev;
if(prev->left != -1) {
if(prev->left < sel->got)
RETURN(RC_FAIL);
prev->left -= sel->got;
}
prev->got += sel->got;
sel = stck->cur_ptr = prev;
if(!sel) break;
tlv_constr = 1;
continue;
} else {
sel = stck->cur_ptr = 0;
break; /* Nothing to wait */
}
}
tl = ber_fetch_tag(buf_ptr, Left, &tlv_tag);
ASN_DEBUG("fetch tag(size=%ld,L=%ld), %sstack, left=%ld, wn=%ld, tl=%ld",
(long)size, (long)Left, sel?"":"!",
(long)(sel?sel->left:0),
(long)(sel?sel->want_nulls:0),
(long)tl);
switch(tl) {
case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE);
}
tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr);
ll = ber_fetch_length(tlv_constr,
(const char *)buf_ptr + tl,Left - tl,&tlv_len);
ASN_DEBUG("Got tag=%s, tc=%d, left=%ld, tl=%ld, len=%ld, ll=%ld",
ber_tlv_tag_string(tlv_tag), tlv_constr,
(long)Left, (long)tl, (long)tlv_len, (long)ll);
switch(ll) {
case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE);
}
if(sel && sel->want_nulls
&& ((const uint8_t *)buf_ptr)[0] == 0
&& ((const uint8_t *)buf_ptr)[1] == 0)
{
ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
if(type_variant == ASN_OSUBV_ANY
&& (tag_mode != 1 || sel->cont_level))
APPEND("\0\0", 2);
ADVANCE(2);
sel->got += 2;
if(sel->left != -1) {
sel->left -= 2; /* assert(sel->left >= 2) */
}
sel->want_nulls--;
if(sel->want_nulls == 0) {
/* Move to the next expectation */
sel->left = 0;
tlv_constr = 1;
}
continue;
}
/*
* Set up expected tags,
* depending on ASN.1 type being decoded.
*/
switch(type_variant) {
case ASN_OSUBV_BIT:
/* X.690: 8.6.4.1, NOTE 2 */
/* Fall through */
case ASN_OSUBV_STR:
default:
if(sel) {
int level = sel->cont_level;
if(level < td->all_tags_count) {
expected_tag = td->all_tags[level];
break;
} else if(td->all_tags_count) {
expected_tag = td->all_tags
[td->all_tags_count - 1];
break;
}
/* else, Fall through */
}
/* Fall through */
case ASN_OSUBV_ANY:
expected_tag = tlv_tag;
break;
}
if(tlv_tag != expected_tag) {
char buf[2][32];
ber_tlv_tag_snprint(tlv_tag,
buf[0], sizeof(buf[0]));
ber_tlv_tag_snprint(td->tags[td->tags_count-1],
buf[1], sizeof(buf[1]));
ASN_DEBUG("Tag does not match expectation: %s != %s",
buf[0], buf[1]);
RETURN(RC_FAIL);
}
tlvl = tl + ll; /* Combined length of T and L encoding */
if((tlv_len + tlvl) < 0) {
/* tlv_len value is too big */
ASN_DEBUG("TLV encoding + length (%ld) is too big",
(long)tlv_len);
RETURN(RC_FAIL);
}
/*
* Append a new expectation.
*/
sel = OS__add_stack_el(stck);
if(!sel) RETURN(RC_FAIL);
sel->tag = tlv_tag;
sel->want_nulls = (tlv_len==-1);
if(sel->prev && sel->prev->left != -1) {
/* Check that the parent frame is big enough */
if(sel->prev->left < tlvl + (tlv_len==-1?0:tlv_len))
RETURN(RC_FAIL);
if(tlv_len == -1)
sel->left = sel->prev->left - tlvl;
else
sel->left = tlv_len;
} else {
sel->left = tlv_len;
}
if(type_variant == ASN_OSUBV_ANY
&& (tag_mode != 1 || sel->cont_level))
APPEND(buf_ptr, tlvl);
sel->got += tlvl;
ADVANCE(tlvl);
ASN_DEBUG("+EXPECT2 got=%ld left=%ld, wn=%d, clvl=%d",
(long)sel->got, (long)sel->left,
sel->want_nulls, sel->cont_level);
} while(tlv_constr);
if(sel == NULL) {
/* Finished operation, "phase out" */
ASN_DEBUG("Phase out");
_CH_PHASE(ctx, +3);
break;
}
NEXT_PHASE(ctx);
/* Fall through */
case 2:
stck = (struct _stack *)ctx->ptr;
sel = stck->cur_ptr;
ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld, alrg=%ld, wn=%d",
(long)sel->left, (long)size, (long)sel->got,
sel->want_nulls);
{
ber_tlv_len_t len;
assert(sel->left >= 0);
len = ((ber_tlv_len_t)size < sel->left)
? (ber_tlv_len_t)size : sel->left;
if(len > 0) {
if(type_variant == ASN_OSUBV_BIT
&& sel->bits_chopped == 0) {
/* Put the unused-bits-octet away */
st->bits_unused = *(const uint8_t *)buf_ptr;
APPEND(((const char *)buf_ptr+1), (len - 1));
sel->bits_chopped = 1;
} else {
APPEND(buf_ptr, len);
}
ADVANCE(len);
sel->left -= len;
sel->got += len;
}
if(sel->left) {
ASN_DEBUG("OS left %ld, size = %ld, wn=%d\n",
(long)sel->left, (long)size, sel->want_nulls);
RETURN(RC_WMORE);
}
PREV_PHASE(ctx);
goto phase1;
}
break;
case 3:
phase3:
/*
* Primitive form, no stack required.
*/
assert(ctx->left >= 0);
if(size < (size_t)ctx->left) {
if(!size) RETURN(RC_WMORE);
if(type_variant == ASN_OSUBV_BIT && !ctx->context) {
st->bits_unused = *(const uint8_t *)buf_ptr;
ctx->left--;
ADVANCE(1);
}
APPEND(buf_ptr, size);
assert(ctx->context > 0);
ctx->left -= size;
ADVANCE(size);
RETURN(RC_WMORE);
} else {
if(type_variant == ASN_OSUBV_BIT
&& !ctx->context && ctx->left) {
st->bits_unused = *(const uint8_t *)buf_ptr;
ctx->left--;
ADVANCE(1);
}
APPEND(buf_ptr, ctx->left);
ADVANCE(ctx->left);
ctx->left = 0;
NEXT_PHASE(ctx);
}
break;
}
if(sel) {
ASN_DEBUG("3sel p=%p, wn=%d, l=%ld, g=%ld, size=%ld",
sel->prev, sel->want_nulls,
(long)sel->left, (long)sel->got, (long)size);
if(sel->prev || sel->want_nulls > 1 || sel->left > 0) {
RETURN(RC_WMORE);
}
}
/*
* BIT STRING-specific processing.
*/
if(type_variant == ASN_OSUBV_BIT && st->size) {
/* Finalize BIT STRING: zero out unused bits. */
st->buf[st->size-1] &= 0xff << st->bits_unused;
}
ASN_DEBUG("Took %ld bytes to encode %s: [%s]:%ld",
(long)consumed_myself, td->name,
(type_variant == ASN_OSUBV_STR) ? (char *)st->buf : "",
(long)st->size);
RETURN(RC_OK);
}
/*
* Encode OCTET STRING type using DER.
*/
asn_enc_rval_t
OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_enc_rval_t er;
asn_OCTET_STRING_specifics_t *specs = td->specifics
? (asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_DEF_OCTET_STRING_specs;
BIT_STRING_t *st = (BIT_STRING_t *)sptr;
enum asn_OS_Subvariant type_variant = specs->subvariant;
int fix_last_byte = 0;
ASN_DEBUG("%s %s as OCTET STRING",
cb?"Estimating":"Encoding", td->name);
/*
* Write tags.
*/
if(type_variant != ASN_OSUBV_ANY || tag_mode == 1) {
er.encoded = der_write_tags(td,
(type_variant == ASN_OSUBV_BIT) + st->size,
tag_mode, type_variant == ASN_OSUBV_ANY, tag,
cb, app_key);
if(er.encoded == -1) {
er.failed_type = td;
er.structure_ptr = sptr;
return er;
}
} else {
/* Disallow: [] IMPLICIT ANY */
assert(type_variant != ASN_OSUBV_ANY || tag_mode != -1);
er.encoded = 0;
}
if(!cb) {
er.encoded += (type_variant == ASN_OSUBV_BIT) + st->size;
ASN__ENCODED_OK(er);
}
/*
* Prepare to deal with the last octet of BIT STRING.
*/
if(type_variant == ASN_OSUBV_BIT) {
uint8_t b = st->bits_unused & 0x07;
if(b && st->size) fix_last_byte = 1;
ASN__CALLBACK(&b, 1);
er.encoded++;
}
/* Invoke callback for the main part of the buffer */
ASN__CALLBACK(st->buf, st->size - fix_last_byte);
/* The last octet should be stripped off the unused bits */
if(fix_last_byte) {
uint8_t b = st->buf[st->size-1] & (0xff << st->bits_unused);
ASN__CALLBACK(&b, 1);
}
er.encoded += st->size;
ASN__ENCODED_OK(er);
cb_failed:
ASN__ENCODE_FAILED;
}
asn_enc_rval_t
OCTET_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
const char * const h2c = "0123456789ABCDEF";
const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
asn_enc_rval_t er;
char scratch[16 * 3 + 4];
char *p = scratch;
uint8_t *buf;
uint8_t *end;
size_t i;
if(!st || (!st->buf && st->size))
ASN__ENCODE_FAILED;
er.encoded = 0;
/*
* Dump the contents of the buffer in hexadecimal.
*/
buf = st->buf;
end = buf + st->size;
if(flags & XER_F_CANONICAL) {
char *scend = scratch + (sizeof(scratch) - 2);
for(; buf < end; buf++) {
if(p >= scend) {
ASN__CALLBACK(scratch, p - scratch);
er.encoded += p - scratch;
p = scratch;
}
*p++ = h2c[(*buf >> 4) & 0x0F];
*p++ = h2c[*buf & 0x0F];
}
ASN__CALLBACK(scratch, p-scratch); /* Dump the rest */
er.encoded += p - scratch;
} else {
for(i = 0; buf < end; buf++, i++) {
if(!(i % 16) && (i || st->size > 16)) {
ASN__CALLBACK(scratch, p-scratch);
er.encoded += (p-scratch);
p = scratch;
ASN__TEXT_INDENT(1, ilevel);
}
*p++ = h2c[(*buf >> 4) & 0x0F];
*p++ = h2c[*buf & 0x0F];
*p++ = 0x20;
}
if(p - scratch) {
p--; /* Remove the tail space */
ASN__CALLBACK(scratch, p-scratch); /* Dump the rest */
er.encoded += p - scratch;
if(st->size > 16)
ASN__TEXT_INDENT(1, ilevel-1);
}
}
ASN__ENCODED_OK(er);
cb_failed:
ASN__ENCODE_FAILED;
}
static const struct OCTET_STRING__xer_escape_table_s {
const char *string;
int size;
} OCTET_STRING__xer_escape_table[] = {
#define OSXET(s) { s, sizeof(s) - 1 }
OSXET("\074\156\165\154\057\076"), /* */
OSXET("\074\163\157\150\057\076"), /* */
OSXET("\074\163\164\170\057\076"), /* */
OSXET("\074\145\164\170\057\076"), /* */
OSXET("\074\145\157\164\057\076"), /* */
OSXET("\074\145\156\161\057\076"), /* */
OSXET("\074\141\143\153\057\076"), /* */
OSXET("\074\142\145\154\057\076"), /* */
OSXET("\074\142\163\057\076"), /* */
OSXET("\011"), /* \t */
OSXET("\012"), /* \n */
OSXET("\074\166\164\057\076"), /* */
OSXET("\074\146\146\057\076"), /* */
OSXET("\015"), /* \r */
OSXET("\074\163\157\057\076"), /* */
OSXET("\074\163\151\057\076"), /* */
OSXET("\074\144\154\145\057\076"), /* */
OSXET("\074\144\143\061\057\076"), /* */
OSXET("\074\144\143\062\057\076"), /* */
OSXET("\074\144\143\063\057\076"), /* */
OSXET("\074\144\143\064\057\076"), /* */
OSXET("\074\156\141\153\057\076"), /* */
OSXET("\074\163\171\156\057\076"), /* */
OSXET("\074\145\164\142\057\076"), /* */
OSXET("\074\143\141\156\057\076"), /* */
OSXET("\074\145\155\057\076"), /* */
OSXET("\074\163\165\142\057\076"), /* */
OSXET("\074\145\163\143\057\076"), /* */
OSXET("\074\151\163\064\057\076"), /* */
OSXET("\074\151\163\063\057\076"), /* */
OSXET("\074\151\163\062\057\076"), /* */
OSXET("\074\151\163\061\057\076"), /* */
{ 0, 0 }, /* " " */
{ 0, 0 }, /* ! */
{ 0, 0 }, /* \" */
{ 0, 0 }, /* # */
{ 0, 0 }, /* $ */
{ 0, 0 }, /* % */
OSXET("\046\141\155\160\073"), /* & */
{ 0, 0 }, /* ' */
{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* ()*+,-./ */
{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* 01234567 */
{0,0},{0,0},{0,0},{0,0}, /* 89:; */
OSXET("\046\154\164\073"), /* < */
{ 0, 0 }, /* = */
OSXET("\046\147\164\073"), /* > */
};
static int
OS__check_escaped_control_char(const void *buf, int size) {
size_t i;
/*
* Inefficient algorithm which translates the escape sequences
* defined above into characters. Returns -1 if not found.
* TODO: replace by a faster algorithm (bsearch(), hash or
* nested table lookups).
*/
for(i = 0; i < 32 /* Don't spend time on the bottom half */; i++) {
const struct OCTET_STRING__xer_escape_table_s *el;
el = &OCTET_STRING__xer_escape_table[i];
if(el->size == size && memcmp(buf, el->string, size) == 0)
return i;
}
return -1;
}
static int
OCTET_STRING__handle_control_chars(void *struct_ptr, const void *chunk_buf, size_t chunk_size) {
/*
* This might be one of the escape sequences
* for control characters. Check it out.
* #11.15.5
*/
int control_char = OS__check_escaped_control_char(chunk_buf,chunk_size);
if(control_char >= 0) {
OCTET_STRING_t *st = (OCTET_STRING_t *)struct_ptr;
void *p = REALLOC(st->buf, st->size + 2);
if(p) {
st->buf = (uint8_t *)p;
st->buf[st->size++] = control_char;
st->buf[st->size] = '\0'; /* nul-termination */
return 0;
}
}
return -1; /* No, it's not */
}
asn_enc_rval_t
OCTET_STRING_encode_xer_utf8(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
asn_enc_rval_t er;
uint8_t *buf, *end;
uint8_t *ss; /* Sequence start */
ssize_t encoded_len = 0;
(void)ilevel; /* Unused argument */
(void)flags; /* Unused argument */
if(!st || (!st->buf && st->size))
ASN__ENCODE_FAILED;
buf = st->buf;
end = buf + st->size;
for(ss = buf; buf < end; buf++) {
unsigned int ch = *buf;
int s_len; /* Special encoding sequence length */
/*
* Escape certain characters: X.680/11.15
*/
if(ch < sizeof(OCTET_STRING__xer_escape_table)
/sizeof(OCTET_STRING__xer_escape_table[0])
&& (s_len = OCTET_STRING__xer_escape_table[ch].size)) {
if(((buf - ss) && cb(ss, buf - ss, app_key) < 0)
|| cb(OCTET_STRING__xer_escape_table[ch].string, s_len,
app_key) < 0)
ASN__ENCODE_FAILED;
encoded_len += (buf - ss) + s_len;
ss = buf + 1;
}
}
encoded_len += (buf - ss);
if((buf - ss) && cb(ss, buf - ss, app_key) < 0)
ASN__ENCODE_FAILED;
er.encoded = encoded_len;
ASN__ENCODED_OK(er);
}
/*
* Convert from hexadecimal format (cstring): "AB CD EF"
*/
static ssize_t OCTET_STRING__convert_hexadecimal(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
const char *chunk_stop = (const char *)chunk_buf;
const char *p = chunk_stop;
const char *pend = p + chunk_size;
unsigned int clv = 0;
int half = 0; /* Half bit */
uint8_t *buf;
/* Reallocate buffer according to high cap estimation */
ssize_t _ns = st->size + (chunk_size + 1) / 2;
void *nptr = REALLOC(st->buf, _ns + 1);
if(!nptr) return -1;
st->buf = (uint8_t *)nptr;
buf = st->buf + st->size;
/*
* If something like " a b c " appears here, the " a b":3 will be
* converted, and the rest skipped. That is, unless buf_size is greater
* than chunk_size, then it'll be equivalent to "ABC0".
*/
for(; p < pend; p++) {
int ch = *(const unsigned char *)p;
switch(ch) {
case 0x09: case 0x0a: case 0x0c: case 0x0d:
case 0x20:
/* Ignore whitespace */
continue;
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
clv = (clv << 4) + (ch - 0x30);
break;
case 0x41: case 0x42: case 0x43: /* ABC */
case 0x44: case 0x45: case 0x46: /* DEF */
clv = (clv << 4) + (ch - 0x41 + 10);
break;
case 0x61: case 0x62: case 0x63: /* abc */
case 0x64: case 0x65: case 0x66: /* def */
clv = (clv << 4) + (ch - 0x61 + 10);
break;
default:
*buf = 0; /* JIC */
return -1;
}
if(half++) {
half = 0;
*buf++ = clv;
chunk_stop = p + 1;
}
}
/*
* Check partial decoding.
*/
if(half) {
if(have_more) {
/*
* Partial specification is fine,
* because no more more PXER_TEXT data is available.
*/
*buf++ = clv << 4;
chunk_stop = p;
}
} else {
chunk_stop = p;
}
st->size = buf - st->buf; /* Adjust the buffer size */
assert(st->size <= _ns);
st->buf[st->size] = 0; /* Courtesy termination */
return (chunk_stop - (const char *)chunk_buf); /* Converted size */
}
/*
* Convert from binary format: "00101011101"
*/
static ssize_t OCTET_STRING__convert_binary(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
BIT_STRING_t *st = (BIT_STRING_t *)sptr;
const char *p = (const char *)chunk_buf;
const char *pend = p + chunk_size;
int bits_unused = st->bits_unused & 0x7;
uint8_t *buf;
/* Reallocate buffer according to high cap estimation */
ssize_t _ns = st->size + (chunk_size + 7) / 8;
void *nptr = REALLOC(st->buf, _ns + 1);
if(!nptr) return -1;
st->buf = (uint8_t *)nptr;
buf = st->buf + st->size;
(void)have_more;
if(bits_unused == 0)
bits_unused = 8;
else if(st->size)
buf--;
/*
* Convert series of 0 and 1 into the octet string.
*/
for(; p < pend; p++) {
int ch = *(const unsigned char *)p;
switch(ch) {
case 0x09: case 0x0a: case 0x0c: case 0x0d:
case 0x20:
/* Ignore whitespace */
break;
case 0x30:
case 0x31:
if(bits_unused-- <= 0) {
*++buf = 0; /* Clean the cell */
bits_unused = 7;
}
*buf |= (ch&1) << bits_unused;
break;
default:
st->bits_unused = bits_unused;
return -1;
}
}
if(bits_unused == 8) {
st->size = buf - st->buf;
st->bits_unused = 0;
} else {
st->size = buf - st->buf + 1;
st->bits_unused = bits_unused;
}
assert(st->size <= _ns);
st->buf[st->size] = 0; /* Courtesy termination */
return chunk_size; /* Converted in full */
}
/*
* Something like strtod(), but with stricter rules.
*/
static int
OS__strtoent(int base, const char *buf, const char *end, int32_t *ret_value) {
int32_t val = 0;
const char *p;
for(p = buf; p < end; p++) {
int ch = *p;
/* Strange huge value */
if((val * base + base) < 0)
return -1;
switch(ch) {
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
val = val * base + (ch - 0x30);
break;
case 0x41: case 0x42: case 0x43: /* ABC */
case 0x44: case 0x45: case 0x46: /* DEF */
val = val * base + (ch - 0x41 + 10);
break;
case 0x61: case 0x62: case 0x63: /* abc */
case 0x64: case 0x65: case 0x66: /* def */
val = val * base + (ch - 0x61 + 10);
break;
case 0x3b: /* ';' */
*ret_value = val;
return (p - buf) + 1;
default:
return -1; /* Character set error */
}
}
*ret_value = -1;
return (p - buf);
}
/*
* Convert from the plain UTF-8 format, expanding entity references: "2 < 3"
*/
static ssize_t OCTET_STRING__convert_entrefs(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
const char *p = (const char *)chunk_buf;
const char *pend = p + chunk_size;
uint8_t *buf;
/* Reallocate buffer */
ssize_t _ns = st->size + chunk_size;
void *nptr = REALLOC(st->buf, _ns + 1);
if(!nptr) return -1;
st->buf = (uint8_t *)nptr;
buf = st->buf + st->size;
/*
* Convert series of 0 and 1 into the octet string.
*/
for(; p < pend; p++) {
int ch = *(const unsigned char *)p;
int len; /* Length of the rest of the chunk */
if(ch != 0x26 /* '&' */) {
*buf++ = ch;
continue; /* That was easy... */
}
/*
* Process entity reference.
*/
len = chunk_size - (p - (const char *)chunk_buf);
if(len == 1 /* "&" */) goto want_more;
if(p[1] == 0x23 /* '#' */) {
const char *pval; /* Pointer to start of digits */
int32_t val = 0; /* Entity reference value */
int base;
if(len == 2 /* "" */) goto want_more;
if(p[2] == 0x78 /* 'x' */)
pval = p + 3, base = 16;
else
pval = p + 2, base = 10;
len = OS__strtoent(base, pval, p + len, &val);
if(len == -1) {
/* Invalid charset. Just copy verbatim. */
*buf++ = ch;
continue;
}
if(!len || pval[len-1] != 0x3b) goto want_more;
assert(val > 0);
p += (pval - p) + len - 1; /* Advance past entref */
if(val < 0x80) {
*buf++ = (char)val;
} else if(val < 0x800) {
*buf++ = 0xc0 | ((val >> 6));
*buf++ = 0x80 | ((val & 0x3f));
} else if(val < 0x10000) {
*buf++ = 0xe0 | ((val >> 12));
*buf++ = 0x80 | ((val >> 6) & 0x3f);
*buf++ = 0x80 | ((val & 0x3f));
} else if(val < 0x200000) {
*buf++ = 0xf0 | ((val >> 18));
*buf++ = 0x80 | ((val >> 12) & 0x3f);
*buf++ = 0x80 | ((val >> 6) & 0x3f);
*buf++ = 0x80 | ((val & 0x3f));
} else if(val < 0x4000000) {
*buf++ = 0xf8 | ((val >> 24));
*buf++ = 0x80 | ((val >> 18) & 0x3f);
*buf++ = 0x80 | ((val >> 12) & 0x3f);
*buf++ = 0x80 | ((val >> 6) & 0x3f);
*buf++ = 0x80 | ((val & 0x3f));
} else {
*buf++ = 0xfc | ((val >> 30) & 0x1);
*buf++ = 0x80 | ((val >> 24) & 0x3f);
*buf++ = 0x80 | ((val >> 18) & 0x3f);
*buf++ = 0x80 | ((val >> 12) & 0x3f);
*buf++ = 0x80 | ((val >> 6) & 0x3f);
*buf++ = 0x80 | ((val & 0x3f));
}
} else {
/*
* Ugly, limited parsing of & > <
*/
char *sc = (char *)memchr(p, 0x3b, len > 5 ? 5 : len);
if(!sc) goto want_more;
if((sc - p) == 4
&& p[1] == 0x61 /* 'a' */
&& p[2] == 0x6d /* 'm' */
&& p[3] == 0x70 /* 'p' */) {
*buf++ = 0x26;
p = sc;
continue;
}
if((sc - p) == 3) {
if(p[1] == 0x6c) {
*buf = 0x3c; /* '<' */
} else if(p[1] == 0x67) {
*buf = 0x3e; /* '>' */
} else {
/* Unsupported entity reference */
*buf++ = ch;
continue;
}
if(p[2] != 0x74) {
/* Unsupported entity reference */
*buf++ = ch;
continue;
}
buf++;
p = sc;
continue;
}
/* Unsupported entity reference */
*buf++ = ch;
}
continue;
want_more:
if(have_more) {
/*
* We know that no more data (of the same type)
* is coming. Copy the rest verbatim.
*/
*buf++ = ch;
continue;
}
chunk_size = (p - (const char *)chunk_buf);
/* Processing stalled: need more data */
break;
}
st->size = buf - st->buf;
assert(st->size <= _ns);
st->buf[st->size] = 0; /* Courtesy termination */
return chunk_size; /* Converted in full */
}
/*
* Decode OCTET STRING from the XML element's body.
*/
static asn_dec_rval_t
OCTET_STRING__decode_xer(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, void **sptr,
const char *opt_mname, const void *buf_ptr, size_t size,
int (*opt_unexpected_tag_decoder)
(void *struct_ptr, const void *chunk_buf, size_t chunk_size),
ssize_t (*body_receiver)
(void *struct_ptr, const void *chunk_buf, size_t chunk_size,
int have_more)
) {
OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr;
asn_OCTET_STRING_specifics_t *specs = td->specifics
? (asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_DEF_OCTET_STRING_specs;
const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
asn_struct_ctx_t *ctx; /* Per-structure parser context */
asn_dec_rval_t rval; /* Return value from the decoder */
int st_allocated;
/*
* Create the string if does not exist.
*/
if(!st) {
st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
*sptr = (void *)st;
if(!st) goto sta_failed;
st_allocated = 1;
} else {
st_allocated = 0;
}
if(!st->buf) {
/* This is separate from above section */
st->buf = (uint8_t *)CALLOC(1, 1);
if(!st->buf) {
if(st_allocated) {
*sptr = 0;
goto stb_failed;
} else {
goto sta_failed;
}
}
}
/* Restore parsing context */
ctx = (asn_struct_ctx_t *)(((char *)*sptr) + specs->ctx_offset);
return xer_decode_general(opt_codec_ctx, ctx, *sptr, xml_tag,
buf_ptr, size, opt_unexpected_tag_decoder, body_receiver);
stb_failed:
FREEMEM(st);
sta_failed:
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
}
/*
* Decode OCTET STRING from the hexadecimal data.
*/
asn_dec_rval_t
OCTET_STRING_decode_xer_hex(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, void **sptr,
const char *opt_mname, const void *buf_ptr, size_t size) {
return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
buf_ptr, size, 0, OCTET_STRING__convert_hexadecimal);
}
/*
* Decode OCTET STRING from the binary (0/1) data.
*/
asn_dec_rval_t
OCTET_STRING_decode_xer_binary(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, void **sptr,
const char *opt_mname, const void *buf_ptr, size_t size) {
return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
buf_ptr, size, 0, OCTET_STRING__convert_binary);
}
/*
* Decode OCTET STRING from the string (ASCII/UTF-8) data.
*/
asn_dec_rval_t
OCTET_STRING_decode_xer_utf8(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, void **sptr,
const char *opt_mname, const void *buf_ptr, size_t size) {
return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
buf_ptr, size,
OCTET_STRING__handle_control_chars,
OCTET_STRING__convert_entrefs);
}
static int
OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
size_t units, unsigned int bpc, unsigned int unit_bits,
long lb, long ub, asn_per_constraints_t *pc) {
uint8_t *end = buf + units * bpc;
ASN_DEBUG("Expanding %d characters into (%ld..%ld):%d",
(int)units, lb, ub, unit_bits);
/* X.691: 27.5.4 */
if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
/* Decode without translation */
lb = 0;
} else if(pc && pc->code2value) {
if(unit_bits > 16)
return 1; /* FATAL: can't have constrained
* UniversalString with more than
* 16 million code points */
for(; buf < end; buf += bpc) {
int value;
int code = per_get_few_bits(po, unit_bits);
if(code < 0) return -1; /* WMORE */
value = pc->code2value(code);
if(value < 0) {
ASN_DEBUG("Code %d (0x%02x) is"
" not in map (%ld..%ld)",
code, code, lb, ub);
return 1; /* FATAL */
}
switch(bpc) {
case 1: *buf = value; break;
case 2: buf[0] = value >> 8; buf[1] = value; break;
case 4: buf[0] = value >> 24; buf[1] = value >> 16;
buf[2] = value >> 8; buf[3] = value; break;
}
}
return 0;
}
/* Shortcut the no-op copying to the aligned structure */
if(lb == 0 && (unit_bits == 8 * bpc)) {
return per_get_many_bits(po, buf, 0, unit_bits * units);
}
for(; buf < end; buf += bpc) {
int code = per_get_few_bits(po, unit_bits);
int ch = code + lb;
if(code < 0) return -1; /* WMORE */
if(ch > ub) {
ASN_DEBUG("Code %d is out of range (%ld..%ld)",
ch, lb, ub);
return 1; /* FATAL */
}
switch(bpc) {
case 1: *buf = ch; break;
case 2: buf[0] = ch >> 8; buf[1] = ch; break;
case 4: buf[0] = ch >> 24; buf[1] = ch >> 16;
buf[2] = ch >> 8; buf[3] = ch; break;
}
}
return 0;
}
static int
OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf,
size_t units, unsigned int bpc, unsigned int unit_bits,
long lb, long ub, asn_per_constraints_t *pc) {
const uint8_t *end = buf + units * bpc;
ASN_DEBUG("Squeezing %d characters into (%ld..%ld):%d (%d bpc)",
(int)units, lb, ub, unit_bits, bpc);
/* X.691: 27.5.4 */
if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
/* Encode as is */
lb = 0;
} else if(pc && pc->value2code) {
for(; buf < end; buf += bpc) {
int code;
uint32_t value;
switch(bpc) {
case 1: value = *(const uint8_t *)buf; break;
case 2: value = (buf[0] << 8) | buf[1]; break;
case 4: value = (buf[0] << 24) | (buf[1] << 16)
| (buf[2] << 8) | buf[3]; break;
default: return -1;
}
code = pc->value2code(value);
if(code < 0) {
ASN_DEBUG("Character %d (0x%02x) is"
" not in map (%ld..%ld)",
*buf, *buf, lb, ub);
return -1;
}
if(per_put_few_bits(po, code, unit_bits))
return -1;
}
}
/* Shortcut the no-op copying to the aligned structure */
if(lb == 0 && (unit_bits == 8 * bpc)) {
return per_put_many_bits(po, buf, unit_bits * units);
}
for(ub -= lb; buf < end; buf += bpc) {
int ch;
uint32_t value;
switch(bpc) {
case 1: value = *(const uint8_t *)buf; break;
case 2: value = (buf[0] << 8) | buf[1]; break;
case 4: value = (buf[0] << 24) | (buf[1] << 16)
| (buf[2] << 8) | buf[3]; break;
default: return -1;
}
ch = value - lb;
if(ch < 0 || ch > ub) {
ASN_DEBUG("Character %d (0x%02x)"
" is out of range (%ld..%ld)",
*buf, *buf, lb, ub + lb);
return -1;
}
if(per_put_few_bits(po, ch, unit_bits))
return -1;
}
return 0;
}
asn_dec_rval_t
OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
void **sptr, asn_per_data_t *pd) {
asn_OCTET_STRING_specifics_t *specs = td->specifics
? (asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_DEF_OCTET_STRING_specs;
asn_per_constraints_t *pc = constraints ? constraints
: td->per_constraints;
asn_per_constraint_t *cval;
asn_per_constraint_t *csiz;
asn_dec_rval_t rval = { RC_OK, 0 };
BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
ssize_t consumed_myself = 0;
int repeat;
enum {
OS__BPC_BIT = 0,
OS__BPC_CHAR = 1,
OS__BPC_U16 = 2,
OS__BPC_U32 = 4
} bpc; /* Bytes per character */
unsigned int unit_bits;
unsigned int canonical_unit_bits;
(void)opt_codec_ctx;
if(pc) {
cval = &pc->value;
csiz = &pc->size;
} else {
cval = &asn_DEF_OCTET_STRING_constraints.value;
csiz = &asn_DEF_OCTET_STRING_constraints.size;
}
switch(specs->subvariant) {
default:
case ASN_OSUBV_ANY:
ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant);
RETURN(RC_FAIL);
case ASN_OSUBV_BIT:
canonical_unit_bits = unit_bits = 1;
bpc = OS__BPC_BIT;
break;
case ASN_OSUBV_STR:
canonical_unit_bits = unit_bits = 8;
if(cval->flags & APC_CONSTRAINED)
unit_bits = cval->range_bits;
bpc = OS__BPC_CHAR;
break;
case ASN_OSUBV_U16:
canonical_unit_bits = unit_bits = 16;
if(cval->flags & APC_CONSTRAINED)
unit_bits = cval->range_bits;
bpc = OS__BPC_U16;
break;
case ASN_OSUBV_U32:
canonical_unit_bits = unit_bits = 32;
if(cval->flags & APC_CONSTRAINED)
unit_bits = cval->range_bits;
bpc = OS__BPC_U32;
break;
}
/*
* Allocate the string.
*/
if(!st) {
st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
if(!st) RETURN(RC_FAIL);
}
ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d",
csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
if(csiz->flags & APC_EXTENSIBLE) {
int inext = per_get_few_bits(pd, 1);
if(inext < 0) RETURN(RC_WMORE);
if(inext) {
csiz = &asn_DEF_OCTET_STRING_constraints.size;
cval = &asn_DEF_OCTET_STRING_constraints.value;
unit_bits = canonical_unit_bits;
}
}
if(csiz->effective_bits >= 0) {
FREEMEM(st->buf);
if(bpc) {
st->size = csiz->upper_bound * bpc;
} else {
st->size = (csiz->upper_bound + 7) >> 3;
}
st->buf = (uint8_t *)MALLOC(st->size + 1);
if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
}
/* X.691, #16.5: zero-length encoding */
/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
if(csiz->effective_bits == 0) {
int ret;
if(bpc) {
ASN_DEBUG("Encoding OCTET STRING size %ld",
csiz->upper_bound);
ret = OCTET_STRING_per_get_characters(pd, st->buf,
csiz->upper_bound, bpc, unit_bits,
cval->lower_bound, cval->upper_bound, pc);
if(ret > 0) RETURN(RC_FAIL);
} else {
ASN_DEBUG("Encoding BIT STRING size %ld",
csiz->upper_bound);
ret = per_get_many_bits(pd, st->buf, 0,
unit_bits * csiz->upper_bound);
}
if(ret < 0) RETURN(RC_WMORE);
consumed_myself += unit_bits * csiz->upper_bound;
st->buf[st->size] = 0;
if(bpc == 0) {
int ubs = (csiz->upper_bound & 0x7);
st->bits_unused = ubs ? 8 - ubs : 0;
}
RETURN(RC_OK);
}
st->size = 0;
do {
ssize_t raw_len;
ssize_t len_bytes;
ssize_t len_bits;
void *p;
int ret;
/* Get the PER length */
raw_len = uper_get_length(pd, csiz->effective_bits, &repeat);
if(raw_len < 0) RETURN(RC_WMORE);
raw_len += csiz->lower_bound;
ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
(long)csiz->effective_bits, (long)raw_len,
repeat ? "repeat" : "once", td->name);
if(bpc) {
len_bytes = raw_len * bpc;
len_bits = len_bytes * unit_bits;
} else {
len_bits = raw_len;
len_bytes = (len_bits + 7) >> 3;
if(len_bits & 0x7)
st->bits_unused = 8 - (len_bits & 0x7);
/* len_bits be multiple of 16K if repeat is set */
}
p = REALLOC(st->buf, st->size + len_bytes + 1);
if(!p) RETURN(RC_FAIL);
st->buf = (uint8_t *)p;
if(bpc) {
ret = OCTET_STRING_per_get_characters(pd,
&st->buf[st->size], raw_len, bpc, unit_bits,
cval->lower_bound, cval->upper_bound, pc);
if(ret > 0) RETURN(RC_FAIL);
} else {
ret = per_get_many_bits(pd, &st->buf[st->size],
0, len_bits);
}
if(ret < 0) RETURN(RC_WMORE);
st->size += len_bytes;
} while(repeat);
st->buf[st->size] = 0; /* nul-terminate */
return rval;
}
asn_enc_rval_t
OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_OCTET_STRING_specifics_t *specs = td->specifics
? (asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_DEF_OCTET_STRING_specs;
asn_per_constraints_t *pc = constraints ? constraints
: td->per_constraints;
asn_per_constraint_t *cval;
asn_per_constraint_t *csiz;
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
asn_enc_rval_t er = { 0, 0, 0 };
int inext = 0; /* Lies not within extension root */
unsigned int unit_bits;
unsigned int canonical_unit_bits;
unsigned int sizeinunits;
const uint8_t *buf;
int ret;
enum {
OS__BPC_BIT = 0,
OS__BPC_CHAR = 1,
OS__BPC_U16 = 2,
OS__BPC_U32 = 4
} bpc; /* Bytes per character */
int ct_extensible;
if(!st || (!st->buf && st->size))
ASN__ENCODE_FAILED;
if(pc) {
cval = &pc->value;
csiz = &pc->size;
} else {
cval = &asn_DEF_OCTET_STRING_constraints.value;
csiz = &asn_DEF_OCTET_STRING_constraints.size;
}
ct_extensible = csiz->flags & APC_EXTENSIBLE;
switch(specs->subvariant) {
default:
case ASN_OSUBV_ANY:
ASN__ENCODE_FAILED;
case ASN_OSUBV_BIT:
canonical_unit_bits = unit_bits = 1;
bpc = OS__BPC_BIT;
sizeinunits = st->size * 8 - (st->bits_unused & 0x07);
ASN_DEBUG("BIT STRING of %d bytes, %d bits unused",
sizeinunits, st->bits_unused);
break;
case ASN_OSUBV_STR:
canonical_unit_bits = unit_bits = 8;
if(cval->flags & APC_CONSTRAINED)
unit_bits = cval->range_bits;
bpc = OS__BPC_CHAR;
sizeinunits = st->size;
break;
case ASN_OSUBV_U16:
canonical_unit_bits = unit_bits = 16;
if(cval->flags & APC_CONSTRAINED)
unit_bits = cval->range_bits;
bpc = OS__BPC_U16;
sizeinunits = st->size / 2;
break;
case ASN_OSUBV_U32:
canonical_unit_bits = unit_bits = 32;
if(cval->flags & APC_CONSTRAINED)
unit_bits = cval->range_bits;
bpc = OS__BPC_U32;
sizeinunits = st->size / 4;
break;
}
ASN_DEBUG("Encoding %s into %d units of %d bits"
" (%ld..%ld, effective %d)%s",
td->name, sizeinunits, unit_bits,
csiz->lower_bound, csiz->upper_bound,
csiz->effective_bits, ct_extensible ? " EXT" : "");
/* Figure out whether size lies within PER visible constraint */
if(csiz->effective_bits >= 0) {
if((int)sizeinunits < csiz->lower_bound
|| (int)sizeinunits > csiz->upper_bound) {
if(ct_extensible) {
cval = &asn_DEF_OCTET_STRING_constraints.value;
csiz = &asn_DEF_OCTET_STRING_constraints.size;
unit_bits = canonical_unit_bits;
inext = 1;
} else
ASN__ENCODE_FAILED;
}
} else {
inext = 0;
}
if(ct_extensible) {
/* Declare whether length is [not] within extension root */
if(per_put_few_bits(po, inext, 1))
ASN__ENCODE_FAILED;
}
/* X.691, #16.5: zero-length encoding */
/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
if(csiz->effective_bits >= 0) {
ASN_DEBUG("Encoding %d bytes (%ld), length in %d bits",
st->size, sizeinunits - csiz->lower_bound,
csiz->effective_bits);
ret = per_put_few_bits(po, sizeinunits - csiz->lower_bound,
csiz->effective_bits);
if(ret) ASN__ENCODE_FAILED;
if(bpc) {
ret = OCTET_STRING_per_put_characters(po, st->buf,
sizeinunits, bpc, unit_bits,
cval->lower_bound, cval->upper_bound, pc);
} else {
ret = per_put_many_bits(po, st->buf,
sizeinunits * unit_bits);
}
if(ret) ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
ASN_DEBUG("Encoding %d bytes", st->size);
if(sizeinunits == 0) {
if(uper_put_length(po, 0))
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
buf = st->buf;
while(sizeinunits) {
ssize_t maySave = uper_put_length(po, sizeinunits);
if(maySave < 0) ASN__ENCODE_FAILED;
ASN_DEBUG("Encoding %ld of %ld",
(long)maySave, (long)sizeinunits);
if(bpc) {
ret = OCTET_STRING_per_put_characters(po, buf,
maySave, bpc, unit_bits,
cval->lower_bound, cval->upper_bound, pc);
} else {
ret = per_put_many_bits(po, buf, maySave * unit_bits);
}
if(ret) ASN__ENCODE_FAILED;
if(bpc)
buf += maySave * bpc;
else
buf += maySave >> 3;
sizeinunits -= maySave;
assert(!(maySave & 0x07) || !sizeinunits);
}
ASN__ENCODED_OK(er);
}
int
OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
const char * const h2c = "0123456789ABCDEF";
const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
char scratch[16 * 3 + 4];
char *p = scratch;
uint8_t *buf;
uint8_t *end;
size_t i;
(void)td; /* Unused argument */
if(!st || (!st->buf && st->size))
return (cb("", 8, app_key) < 0) ? -1 : 0;
/*
* Dump the contents of the buffer in hexadecimal.
*/
buf = st->buf;
end = buf + st->size;
for(i = 0; buf < end; buf++, i++) {
if(!(i % 16) && (i || st->size > 16)) {
if(cb(scratch, p - scratch, app_key) < 0)
return -1;
_i_INDENT(1);
p = scratch;
}
*p++ = h2c[(*buf >> 4) & 0x0F];
*p++ = h2c[*buf & 0x0F];
*p++ = 0x20;
}
if(p > scratch) {
p--; /* Remove the tail space */
if(cb(scratch, p - scratch, app_key) < 0)
return -1;
}
return 0;
}
int
OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(st && (st->buf || !st->size)) {
return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
} else {
return (cb("", 8, app_key) < 0) ? -1 : 0;
}
}
void
OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
asn_OCTET_STRING_specifics_t *specs;
asn_struct_ctx_t *ctx;
struct _stack *stck;
if(!td || !st)
return;
specs = td->specifics
? (asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_DEF_OCTET_STRING_specs;
ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
ASN_DEBUG("Freeing %s as OCTET STRING", td->name);
if(st->buf) {
FREEMEM(st->buf);
st->buf = 0;
}
/*
* Remove decode-time stack.
*/
stck = (struct _stack *)ctx->ptr;
if(stck) {
while(stck->tail) {
struct _stack_el *sel = stck->tail;
stck->tail = sel->prev;
FREEMEM(sel);
}
FREEMEM(stck);
}
if(!contents_only) {
FREEMEM(st);
}
}
/*
* Conversion routines.
*/
int
OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) {
void *buf;
if(st == 0 || (str == 0 && len)) {
errno = EINVAL;
return -1;
}
/*
* Clear the OCTET STRING.
*/
if(str == NULL) {
FREEMEM(st->buf);
st->buf = 0;
st->size = 0;
return 0;
}
/* Determine the original string size, if not explicitly given */
if(len < 0)
len = strlen(str);
/* Allocate and fill the memory */
buf = MALLOC(len + 1);
if(buf == NULL)
return -1;
memcpy(buf, str, len);
((uint8_t *)buf)[len] = '\0'; /* Couldn't use memcpy(len+1)! */
FREEMEM(st->buf);
st->buf = (uint8_t *)buf;
st->size = len;
return 0;
}
OCTET_STRING_t *
OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td, const char *str, int len) {
asn_OCTET_STRING_specifics_t *specs = td->specifics
? (asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_DEF_OCTET_STRING_specs;
OCTET_STRING_t *st;
st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
if(st && str && OCTET_STRING_fromBuf(st, str, len)) {
FREEMEM(st);
st = NULL;
}
return st;
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/OCTET_STRING.h 0000664 0000000 0000000 00000005411 15245442746 0026445 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _OCTET_STRING_H_
#define _OCTET_STRING_H_
#include
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OCTET_STRING {
uint8_t *buf; /* Buffer with consecutive OCTET_STRING bits */
int size; /* Size of the buffer */
asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */
} OCTET_STRING_t;
extern asn_TYPE_descriptor_t asn_DEF_OCTET_STRING;
asn_struct_free_f OCTET_STRING_free;
asn_struct_print_f OCTET_STRING_print;
asn_struct_print_f OCTET_STRING_print_utf8;
ber_type_decoder_f OCTET_STRING_decode_ber;
der_type_encoder_f OCTET_STRING_encode_der;
xer_type_decoder_f OCTET_STRING_decode_xer_hex; /* Hexadecimal */
xer_type_decoder_f OCTET_STRING_decode_xer_binary; /* 01010111010 */
xer_type_decoder_f OCTET_STRING_decode_xer_utf8; /* ASCII/UTF-8 */
xer_type_encoder_f OCTET_STRING_encode_xer;
xer_type_encoder_f OCTET_STRING_encode_xer_utf8;
per_type_decoder_f OCTET_STRING_decode_uper;
per_type_encoder_f OCTET_STRING_encode_uper;
/******************************
* Handy conversion routines. *
******************************/
/*
* This function clears the previous value of the OCTET STRING (if any)
* and then allocates a new memory with the specified content (str/size).
* If size = -1, the size of the original string will be determined
* using strlen(str).
* If str equals to NULL, the function will silently clear the
* current contents of the OCTET STRING.
* Returns 0 if it was possible to perform operation, -1 otherwise.
*/
int OCTET_STRING_fromBuf(OCTET_STRING_t *s, const char *str, int size);
/* Handy conversion from the C string into the OCTET STRING. */
#define OCTET_STRING_fromString(s, str) OCTET_STRING_fromBuf(s, str, -1)
/*
* Allocate and fill the new OCTET STRING and return a pointer to the newly
* allocated object. NULL is permitted in str: the function will just allocate
* empty OCTET STRING.
*/
OCTET_STRING_t *OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td,
const char *str, int size);
/****************************
* Internally useful stuff. *
****************************/
typedef const struct asn_OCTET_STRING_specifics_s {
/*
* Target structure description.
*/
int struct_size; /* Size of the structure */
int ctx_offset; /* Offset of the asn_struct_ctx_t member */
enum asn_OS_Subvariant {
ASN_OSUBV_ANY, /* The open type (ANY) */
ASN_OSUBV_BIT, /* BIT STRING */
ASN_OSUBV_STR, /* String types, not {BMP,Universal}String */
ASN_OSUBV_U16, /* 16-bit character (BMPString) */
ASN_OSUBV_U32 /* 32-bit character (UniversalString) */
} subvariant;
} asn_OCTET_STRING_specifics_t;
#ifdef __cplusplus
}
#endif
#endif /* _OCTET_STRING_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/PDU.c 0000664 0000000 0000000 00000011024 15245442746 0025121 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#include "PDU.h"
static asn_per_constraints_t asn_PER_type_b_constr_3 GCC_NOTUSED = {
{ APC_CONSTRAINED, 3, 3, 0, 4 } /* (0..4) */,
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
0, 0 /* No PER value map */
};
static asn_TYPE_member_t asn_MBR_b_3[] = {
{ ATF_NOFLAGS, 0, offsetof(struct PDU__b, choice.a),
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
-1, /* IMPLICIT tag at current level */
&asn_DEF_A,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"a"
},
{ ATF_NOFLAGS, 0, offsetof(struct PDU__b, choice.b),
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
+1, /* EXPLICIT tag at current level */
&asn_DEF_B,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"b"
},
{ ATF_NOFLAGS, 0, offsetof(struct PDU__b, choice.c),
(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
-1, /* IMPLICIT tag at current level */
&asn_DEF_C,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"c"
},
{ ATF_NOFLAGS, 0, offsetof(struct PDU__b, choice.d),
(ASN_TAG_CLASS_CONTEXT | (3 << 2)),
-1, /* IMPLICIT tag at current level */
&asn_DEF_D,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"d"
},
{ ATF_NOFLAGS, 0, offsetof(struct PDU__b, choice.e),
(ASN_TAG_CLASS_CONTEXT | (4 << 2)),
-1, /* IMPLICIT tag at current level */
&asn_DEF_E,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"e"
},
};
static const asn_TYPE_tag2member_t asn_MAP_b_tag2el_3[] = {
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* a */
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* b */
{ (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 }, /* c */
{ (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 3, 0, 0 }, /* d */
{ (ASN_TAG_CLASS_CONTEXT | (4 << 2)), 4, 0, 0 } /* e */
};
static asn_CHOICE_specifics_t asn_SPC_b_specs_3 = {
sizeof(struct PDU__b),
offsetof(struct PDU__b, _asn_ctx),
offsetof(struct PDU__b, present),
sizeof(((struct PDU__b *)0)->present),
asn_MAP_b_tag2el_3,
5, /* Count of tags in the map */
0,
-1 /* Extensions start */
};
static /* Use -fall-defs-global to expose */
asn_TYPE_descriptor_t asn_DEF_b_3 = {
"b",
"b",
CHOICE_free,
CHOICE_print,
CHOICE_constraint,
CHOICE_decode_ber,
CHOICE_encode_der,
CHOICE_decode_xer,
CHOICE_encode_xer,
CHOICE_decode_uper,
CHOICE_encode_uper,
CHOICE_outmost_tag,
0, /* No effective tags (pointer) */
0, /* No effective tags (count) */
0, /* No tags (pointer) */
0, /* No tags (count) */
&asn_PER_type_b_constr_3,
asn_MBR_b_3,
5, /* Elements count */
&asn_SPC_b_specs_3 /* Additional specs */
};
static asn_TYPE_member_t asn_MBR_PDU_1[] = {
{ ATF_NOFLAGS, 0, offsetof(struct PDU, a),
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
-1, /* IMPLICIT tag at current level */
&asn_DEF_F,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"a"
},
{ ATF_NOFLAGS, 0, offsetof(struct PDU, b),
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
+1, /* EXPLICIT tag at current level */
&asn_DEF_b_3,
0, /* Defer constraints checking to the member type */
0, /* No PER visible constraints */
0,
"b"
},
};
static const ber_tlv_tag_t asn_DEF_PDU_tags_1[] = {
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
};
static const asn_TYPE_tag2member_t asn_MAP_PDU_tag2el_1[] = {
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* a */
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* b */
};
static asn_SEQUENCE_specifics_t asn_SPC_PDU_specs_1 = {
sizeof(struct PDU),
offsetof(struct PDU, _asn_ctx),
asn_MAP_PDU_tag2el_1,
2, /* Count of tags in the map */
0, 0, 0, /* Optional elements (not needed) */
-1, /* Start extensions */
-1 /* Stop extensions */
};
asn_TYPE_descriptor_t asn_DEF_PDU = {
"PDU",
"PDU",
SEQUENCE_free,
SEQUENCE_print,
SEQUENCE_constraint,
SEQUENCE_decode_ber,
SEQUENCE_encode_der,
SEQUENCE_decode_xer,
SEQUENCE_encode_xer,
SEQUENCE_decode_uper,
SEQUENCE_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_PDU_tags_1,
sizeof(asn_DEF_PDU_tags_1)
/sizeof(asn_DEF_PDU_tags_1[0]), /* 1 */
asn_DEF_PDU_tags_1, /* Same as above */
sizeof(asn_DEF_PDU_tags_1)
/sizeof(asn_DEF_PDU_tags_1[0]), /* 1 */
0, /* No PER visible constraints */
asn_MBR_PDU_1,
2, /* Elements count */
&asn_SPC_PDU_specs_1 /* Additional specs */
};
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/PDU.h 0000664 0000000 0000000 00000002166 15245442746 0025135 0 ustar 00root root 0000000 0000000 /*
* Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
* From ASN.1 module "MyProtocol"
* found in "../../my_protocol.asn"
* `asn1c -fcompound-names -fincludes-quoted -gen-PER`
*/
#ifndef _PDU_H_
#define _PDU_H_
#include "asn_application.h"
/* Including external dependencies */
#include "F.h"
#include "A.h"
#include "B.h"
#include "C.h"
#include "D.h"
#include "E.h"
#include "constr_CHOICE.h"
#include "constr_SEQUENCE.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Dependencies */
typedef enum PDU__b_PR {
PDU__b_PR_NOTHING, /* No components present */
PDU__b_PR_a,
PDU__b_PR_b,
PDU__b_PR_c,
PDU__b_PR_d,
PDU__b_PR_e
} PDU__b_PR;
/* PDU */
typedef struct PDU {
F_t a;
struct PDU__b {
PDU__b_PR present;
union PDU__b_u {
A_t a;
B_t b;
C_t c;
D_t d;
E_t e;
} choice;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} b;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
} PDU_t;
/* Implementation */
extern asn_TYPE_descriptor_t asn_DEF_PDU;
#ifdef __cplusplus
}
#endif
#endif /* _PDU_H_ */
#include "asn_internal.h"
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/asn_SEQUENCE_OF.c 0000664 0000000 0000000 00000001560 15245442746 0027132 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
typedef A_SEQUENCE_OF(void) asn_sequence;
void
asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free) {
asn_sequence *as = (asn_sequence *)asn_sequence_of_x;
if(as) {
void *ptr;
int n;
if(number < 0 || number >= as->count)
return; /* Nothing to delete */
if(_do_free && as->free) {
ptr = as->array[number];
} else {
ptr = 0;
}
/*
* Shift all elements to the left to hide the gap.
*/
--as->count;
for(n = number; n < as->count; n++)
as->array[n] = as->array[n+1];
/*
* Invoke the third-party function only when the state
* of the parent structure is consistent.
*/
if(ptr) as->free(ptr);
}
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/asn_SEQUENCE_OF.h 0000664 0000000 0000000 00000002735 15245442746 0027144 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef ASN_SEQUENCE_OF_H
#define ASN_SEQUENCE_OF_H
#include
#ifdef __cplusplus
extern "C" {
#endif
/*
* SEQUENCE OF is the same as SET OF with a tiny difference:
* the delete operation preserves the initial order of elements
* and thus MAY operate in non-constant time.
*/
#define A_SEQUENCE_OF(type) A_SET_OF(type)
#define ASN_SEQUENCE_ADD(headptr, ptr) \
asn_sequence_add((headptr), (ptr))
/***********************************************
* Implementation of the SEQUENCE OF structure.
*/
#define asn_sequence_add asn_set_add
#define asn_sequence_empty asn_set_empty
/*
* Delete the element from the set by its number (base 0).
* This is NOT a constant-time operation.
* The order of elements is preserved.
* If _do_free is given AND the (*free) is initialized, the element
* will be freed using the custom (*free) function as well.
*/
void asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free);
/*
* Cope with different conversions requirements to/from void in C and C++.
* This is mostly useful for support library.
*/
typedef A_SEQUENCE_OF(void) asn_anonymous_sequence_;
#define _A_SEQUENCE_FROM_VOID(ptr) ((asn_anonymous_sequence_ *)(ptr))
#define _A_CSEQUENCE_FROM_VOID(ptr) ((const asn_anonymous_sequence_ *)(ptr))
#ifdef __cplusplus
}
#endif
#endif /* ASN_SEQUENCE_OF_H */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/asn_SET_OF.c 0000664 0000000 0000000 00000003252 15245442746 0026355 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include
/*
* Add another element into the set.
*/
int
asn_set_add(void *asn_set_of_x, void *ptr) {
asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x);
if(as == 0 || ptr == 0) {
errno = EINVAL; /* Invalid arguments */
return -1;
}
/*
* Make sure there's enough space to insert an element.
*/
if(as->count == as->size) {
int _newsize = as->size ? (as->size << 1) : 4;
void *_new_arr;
_new_arr = REALLOC(as->array, _newsize * sizeof(as->array[0]));
if(_new_arr) {
as->array = (void **)_new_arr;
as->size = _newsize;
} else {
/* ENOMEM */
return -1;
}
}
as->array[as->count++] = ptr;
return 0;
}
void
asn_set_del(void *asn_set_of_x, int number, int _do_free) {
asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x);
if(as) {
void *ptr;
if(number < 0 || number >= as->count)
return;
if(_do_free && as->free) {
ptr = as->array[number];
} else {
ptr = 0;
}
as->array[number] = as->array[--as->count];
/*
* Invoke the third-party function only when the state
* of the parent structure is consistent.
*/
if(ptr) as->free(ptr);
}
}
/*
* Free the contents of the set, do not free the set itself.
*/
void
asn_set_empty(void *asn_set_of_x) {
asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x);
if(as) {
if(as->array) {
if(as->free) {
while(as->count--)
as->free(as->array[as->count]);
}
FREEMEM(as->array);
as->array = 0;
}
as->count = 0;
as->size = 0;
}
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/asn_SET_OF.h 0000664 0000000 0000000 00000003233 15245442746 0026361 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef ASN_SET_OF_H
#define ASN_SET_OF_H
#ifdef __cplusplus
extern "C" {
#endif
#define A_SET_OF(type) \
struct { \
type **array; \
int count; /* Meaningful size */ \
int size; /* Allocated size */ \
void (*free)(type *); \
}
#define ASN_SET_ADD(headptr, ptr) \
asn_set_add((headptr), (ptr))
/*******************************************
* Implementation of the SET OF structure.
*/
/*
* Add another structure into the set by its pointer.
* RETURN VALUES:
* 0 for success and -1/errno for failure.
*/
int asn_set_add(void *asn_set_of_x, void *ptr);
/*
* Delete the element from the set by its number (base 0).
* This is a constant-time operation. The order of elements before the
* deleted ones is guaranteed, the order of elements after the deleted
* one is NOT guaranteed.
* If _do_free is given AND the (*free) is initialized, the element
* will be freed using the custom (*free) function as well.
*/
void asn_set_del(void *asn_set_of_x, int number, int _do_free);
/*
* Empty the contents of the set. Will free the elements, if (*free) is given.
* Will NOT free the set itself.
*/
void asn_set_empty(void *asn_set_of_x);
/*
* Cope with different conversions requirements to/from void in C and C++.
* This is mostly useful for support library.
*/
typedef A_SET_OF(void) asn_anonymous_set_;
#define _A_SET_FROM_VOID(ptr) ((asn_anonymous_set_ *)(ptr))
#define _A_CSET_FROM_VOID(ptr) ((const asn_anonymous_set_ *)(ptr))
#ifdef __cplusplus
}
#endif
#endif /* ASN_SET_OF_H */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/asn_application.h 0000664 0000000 0000000 00000002710 15245442746 0027644 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2004, 2006 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
* Application-level ASN.1 callbacks.
*/
#ifndef ASN_APPLICATION_H
#define ASN_APPLICATION_H
#include "asn_system.h" /* for platform-dependent types */
#include "asn_codecs.h" /* for ASN.1 codecs specifics */
#ifdef __cplusplus
extern "C" {
#endif
/*
* Generic type of an application-defined callback to return various
* types of data to the application.
* EXPECTED RETURN VALUES:
* -1: Failed to consume bytes. Abort the mission.
* Non-negative return values indicate success, and ignored.
*/
typedef int (asn_app_consume_bytes_f)(const void *buffer, size_t size,
void *application_specific_key);
/*
* A callback of this type is called whenever constraint validation fails
* on some ASN.1 type. See "constraints.h" for more details on constraint
* validation.
* This callback specifies a descriptor of the ASN.1 type which failed
* the constraint check, as well as human readable message on what
* particular constraint has failed.
*/
typedef void (asn_app_constraint_failed_f)(void *application_specific_key,
struct asn_TYPE_descriptor_s *type_descriptor_which_failed,
const void *structure_which_failed_ptr,
const char *error_message_format, ...) GCC_PRINTFLIKE(4, 5);
#ifdef __cplusplus
}
#endif
#include "constr_TYPE.h" /* for asn_TYPE_descriptor_t */
#endif /* ASN_APPLICATION_H */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/asn_codecs.h 0000664 0000000 0000000 00000006563 15245442746 0026613 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004, 2005 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef ASN_CODECS_H
#define ASN_CODECS_H
#ifdef __cplusplus
extern "C" {
#endif
struct asn_TYPE_descriptor_s; /* Forward declaration */
/*
* This structure defines a set of parameters that may be passed
* to every ASN.1 encoder or decoder function.
* WARNING: if max_stack_size member is set, and you are calling the
* function pointers of the asn_TYPE_descriptor_t directly,
* this structure must be ALLOCATED ON THE STACK!
* If you can't always satisfy this requirement, use ber_decode(),
* xer_decode() and uper_decode() functions instead.
*/
typedef struct asn_codec_ctx_s {
/*
* Limit the decoder routines to use no (much) more stack than a given
* number of bytes. Most of decoders are stack-based, and this
* would protect against stack overflows if the number of nested
* encodings is high.
* The OCTET STRING, BIT STRING and ANY BER decoders are heap-based,
* and are safe from this kind of overflow.
* A value from getrlimit(RLIMIT_STACK) may be used to initialize
* this variable. Be careful in multithreaded environments, as the
* stack size is rather limited.
*/
size_t max_stack_size; /* 0 disables stack bounds checking */
} asn_codec_ctx_t;
/*
* Type of the return value of the encoding functions (der_encode, xer_encode).
*/
typedef struct asn_enc_rval_s {
/*
* Number of bytes encoded.
* -1 indicates failure to encode the structure.
* In this case, the members below this one are meaningful.
*/
ssize_t encoded;
/*
* Members meaningful when (encoded == -1), for post mortem analysis.
*/
/* Type which cannot be encoded */
struct asn_TYPE_descriptor_s *failed_type;
/* Pointer to the structure of that type */
void *structure_ptr;
} asn_enc_rval_t;
#define ASN__ENCODE_FAILED do { \
asn_enc_rval_t tmp_error; \
tmp_error.encoded = -1; \
tmp_error.failed_type = td; \
tmp_error.structure_ptr = sptr; \
ASN_DEBUG("Failed to encode element %s", td ? td->name : ""); \
return tmp_error; \
} while(0)
#define ASN__ENCODED_OK(rval) do { \
rval.structure_ptr = 0; \
rval.failed_type = 0; \
return rval; \
} while(0)
/*
* Type of the return value of the decoding functions (ber_decode, xer_decode)
*
* Please note that the number of consumed bytes is ALWAYS meaningful,
* even if code==RC_FAIL. This is to indicate the number of successfully
* decoded bytes, hence providing a possibility to fail with more diagnostics
* (i.e., print the offending remainder of the buffer).
*/
enum asn_dec_rval_code_e {
RC_OK, /* Decoded successfully */
RC_WMORE, /* More data expected, call again */
RC_FAIL /* Failure to decode data */
};
typedef struct asn_dec_rval_s {
enum asn_dec_rval_code_e code; /* Result code */
size_t consumed; /* Number of bytes consumed */
} asn_dec_rval_t;
#define ASN__DECODE_FAILED do { \
asn_dec_rval_t tmp_error; \
tmp_error.code = RC_FAIL; \
tmp_error.consumed = 0; \
ASN_DEBUG("Failed to decode element %s", td ? td->name : ""); \
return tmp_error; \
} while(0)
#define ASN__DECODE_STARVED do { \
asn_dec_rval_t tmp_error; \
tmp_error.code = RC_WMORE; \
tmp_error.consumed = 0; \
return tmp_error; \
} while(0)
#ifdef __cplusplus
}
#endif
#endif /* ASN_CODECS_H */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/asn_codecs_prim.c 0000664 0000000 0000000 00000016434 15245442746 0027633 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include
/*
* Decode an always-primitive type.
*/
asn_dec_rval_t
ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td,
void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
asn_dec_rval_t rval;
ber_tlv_len_t length = 0; /* =0 to avoid [incorrect] warning. */
/*
* If the structure is not there, allocate it.
*/
if(st == NULL) {
st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
if(st == NULL) ASN__DECODE_FAILED;
*sptr = (void *)st;
}
ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
td->name, tag_mode);
/*
* Check tags and extract value length.
*/
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
tag_mode, 0, &length, 0);
if(rval.code != RC_OK)
return rval;
ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
/*
* Make sure we have this length.
*/
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
size -= rval.consumed;
if(length > (ber_tlv_len_t)size) {
rval.code = RC_WMORE;
rval.consumed = 0;
return rval;
}
st->size = (int)length;
/* The following better be optimized away. */
if(sizeof(st->size) != sizeof(length)
&& (ber_tlv_len_t)st->size != length) {
st->size = 0;
ASN__DECODE_FAILED;
}
st->buf = (uint8_t *)MALLOC(length + 1);
if(!st->buf) {
st->size = 0;
ASN__DECODE_FAILED;
}
memcpy(st->buf, buf_ptr, length);
st->buf[length] = '\0'; /* Just in case */
rval.code = RC_OK;
rval.consumed += length;
ASN_DEBUG("Took %ld/%ld bytes to encode %s",
(long)rval.consumed,
(long)length, td->name);
return rval;
}
/*
* Encode an always-primitive type using DER.
*/
asn_enc_rval_t
der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr,
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_enc_rval_t erval;
ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
ASN_DEBUG("%s %s as a primitive type (tm=%d)",
cb?"Encoding":"Estimating", td->name, tag_mode);
erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
cb, app_key);
ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
if(erval.encoded == -1) {
erval.failed_type = td;
erval.structure_ptr = sptr;
return erval;
}
if(cb && st->buf) {
if(cb(st->buf, st->size, app_key) < 0) {
erval.encoded = -1;
erval.failed_type = td;
erval.structure_ptr = sptr;
return erval;
}
} else {
assert(st->buf || st->size == 0);
}
erval.encoded += st->size;
ASN__ENCODED_OK(erval);
}
void
ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
int contents_only) {
ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
if(!td || !sptr)
return;
ASN_DEBUG("Freeing %s as a primitive type", td->name);
if(st->buf)
FREEMEM(st->buf);
if(!contents_only)
FREEMEM(st);
}
/*
* Local internal type passed around as an argument.
*/
struct xdp_arg_s {
asn_TYPE_descriptor_t *type_descriptor;
void *struct_key;
xer_primitive_body_decoder_f *prim_body_decoder;
int decoded_something;
int want_more;
};
/*
* Since some kinds of primitive values can be encoded using value-specific
* tags (, , etc), the primitive decoder must
* be supplied with such tags to parse them as needed.
*/
static int
xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
enum xer_pbd_rval bret;
/*
* The chunk_buf is guaranteed to start at '<'.
*/
assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
/*
* Decoding was performed once already. Prohibit doing it again.
*/
if(arg->decoded_something)
return -1;
bret = arg->prim_body_decoder(arg->type_descriptor,
arg->struct_key, chunk_buf, chunk_size);
switch(bret) {
case XPBD_SYSTEM_FAILURE:
case XPBD_DECODER_LIMIT:
case XPBD_BROKEN_ENCODING:
break;
case XPBD_BODY_CONSUMED:
/* Tag decoded successfully */
arg->decoded_something = 1;
/* Fall through */
case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
return 0;
}
return -1;
}
static ssize_t
xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
enum xer_pbd_rval bret;
size_t lead_wsp_size;
if(arg->decoded_something) {
if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
/*
* Example:
* "123 "
* ^- chunk_buf position.
*/
return chunk_size;
}
/*
* Decoding was done once already. Prohibit doing it again.
*/
return -1;
}
if(!have_more) {
/*
* If we've received something like "1", we can't really
* tell whether it is really `1` or `123`, until we know
* that there is no more data coming.
* The have_more argument will be set to 1 once something
* like this is available to the caller of this callback:
* "1want_more = 1;
return -1;
}
lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size);
chunk_buf = (const char *)chunk_buf + lead_wsp_size;
chunk_size -= lead_wsp_size;
bret = arg->prim_body_decoder(arg->type_descriptor,
arg->struct_key, chunk_buf, chunk_size);
switch(bret) {
case XPBD_SYSTEM_FAILURE:
case XPBD_DECODER_LIMIT:
case XPBD_BROKEN_ENCODING:
break;
case XPBD_BODY_CONSUMED:
/* Tag decoded successfully */
arg->decoded_something = 1;
/* Fall through */
case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
return lead_wsp_size + chunk_size;
}
return -1;
}
asn_dec_rval_t
xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td,
void **sptr,
size_t struct_size,
const char *opt_mname,
const void *buf_ptr, size_t size,
xer_primitive_body_decoder_f *prim_body_decoder
) {
const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
asn_struct_ctx_t s_ctx;
struct xdp_arg_s s_arg;
asn_dec_rval_t rc;
/*
* Create the structure if does not exist.
*/
if(!*sptr) {
*sptr = CALLOC(1, struct_size);
if(!*sptr) ASN__DECODE_FAILED;
}
memset(&s_ctx, 0, sizeof(s_ctx));
s_arg.type_descriptor = td;
s_arg.struct_key = *sptr;
s_arg.prim_body_decoder = prim_body_decoder;
s_arg.decoded_something = 0;
s_arg.want_more = 0;
rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
xml_tag, buf_ptr, size,
xer_decode__unexpected_tag, xer_decode__primitive_body);
switch(rc.code) {
case RC_OK:
if(!s_arg.decoded_something) {
char ch;
ASN_DEBUG("Primitive body is not recognized, "
"supplying empty one");
/*
* Decoding opportunity has come and gone.
* Where's the result?
* Try to feed with empty body, see if it eats it.
*/
if(prim_body_decoder(s_arg.type_descriptor,
s_arg.struct_key, &ch, 0)
!= XPBD_BODY_CONSUMED) {
/*
* This decoder does not like empty stuff.
*/
ASN__DECODE_FAILED;
}
}
break;
case RC_WMORE:
/*
* Redo the whole thing later.
* We don't have a context to save intermediate parsing state.
*/
rc.consumed = 0;
break;
case RC_FAIL:
rc.consumed = 0;
if(s_arg.want_more)
rc.code = RC_WMORE;
else
ASN__DECODE_FAILED;
break;
}
return rc;
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/asn_codecs_prim.h 0000664 0000000 0000000 00000003135 15245442746 0027632 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef ASN_CODECS_PRIM_H
#define ASN_CODECS_PRIM_H
#include
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ASN__PRIMITIVE_TYPE_s {
uint8_t *buf; /* Buffer with consecutive primitive encoding bytes */
int size; /* Size of the buffer */
} ASN__PRIMITIVE_TYPE_t; /* Do not use this type directly! */
asn_struct_free_f ASN__PRIMITIVE_TYPE_free;
ber_type_decoder_f ber_decode_primitive;
der_type_encoder_f der_encode_primitive;
/*
* A callback specification for the xer_decode_primitive() function below.
*/
enum xer_pbd_rval {
XPBD_SYSTEM_FAILURE, /* System failure (memory shortage, etc) */
XPBD_DECODER_LIMIT, /* Hit some decoder limitation or deficiency */
XPBD_BROKEN_ENCODING, /* Encoding of a primitive body is broken */
XPBD_NOT_BODY_IGNORE, /* Not a body format, but safe to ignore */
XPBD_BODY_CONSUMED /* Body is recognized and consumed */
};
typedef enum xer_pbd_rval (xer_primitive_body_decoder_f)
(asn_TYPE_descriptor_t *td, void *struct_ptr,
const void *chunk_buf, size_t chunk_size);
/*
* Specific function to decode simple primitive types.
* Also see xer_decode_general() in xer_decoder.h
*/
asn_dec_rval_t xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *type_descriptor,
void **struct_ptr, size_t struct_size,
const char *opt_mname,
const void *buf_ptr, size_t size,
xer_primitive_body_decoder_f *prim_body_decoder
);
#ifdef __cplusplus
}
#endif
#endif /* ASN_CODECS_PRIM_H */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/asn_internal.h 0000664 0000000 0000000 00000010121 15245442746 0027150 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004, 2005, 2007 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
* Declarations internally useful for the ASN.1 support code.
*/
#ifndef ASN_INTERNAL_H
#define ASN_INTERNAL_H
#include "asn_application.h" /* Application-visible API */
#ifndef __NO_ASSERT_H__ /* Include assert.h only for internal use. */
#include /* for assert() macro */
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Environment version might be used to avoid running with the old library */
#define ASN1C_ENVIRONMENT_VERSION 923 /* Compile-time version */
int get_asn1c_environment_version(void); /* Run-time version */
#define CALLOC(nmemb, size) calloc(nmemb, size)
#define MALLOC(size) malloc(size)
#define REALLOC(oldptr, size) realloc(oldptr, size)
#define FREEMEM(ptr) free(ptr)
#define asn_debug_indent 0
#define ASN_DEBUG_INDENT_ADD(i) do{}while(0)
/*
* A macro for debugging the ASN.1 internals.
* You may enable or override it.
*/
#ifndef ASN_DEBUG /* If debugging code is not defined elsewhere... */
#if EMIT_ASN_DEBUG == 1 /* And it was asked to emit this code... */
#ifdef __GNUC__
#ifdef ASN_THREAD_SAFE
/* Thread safety requires sacrifice in output indentation:
* Retain empty definition of ASN_DEBUG_INDENT_ADD. */
#else /* !ASN_THREAD_SAFE */
#undef ASN_DEBUG_INDENT_ADD
#undef asn_debug_indent
int asn_debug_indent;
#define ASN_DEBUG_INDENT_ADD(i) do { asn_debug_indent += i; } while(0)
#endif /* ASN_THREAD_SAFE */
#define ASN_DEBUG(fmt, args...) do { \
int adi = asn_debug_indent; \
while(adi--) fprintf(stderr, " "); \
fprintf(stderr, fmt, ##args); \
fprintf(stderr, " (%s:%d)\n", \
__FILE__, __LINE__); \
} while(0)
#else /* !__GNUC__ */
void ASN_DEBUG_f(const char *fmt, ...);
#define ASN_DEBUG ASN_DEBUG_f
#endif /* __GNUC__ */
#else /* EMIT_ASN_DEBUG != 1 */
static void ASN_DEBUG(const char *fmt, ...) { (void)fmt; }
#endif /* EMIT_ASN_DEBUG */
#endif /* ASN_DEBUG */
/*
* Invoke the application-supplied callback and fail, if something is wrong.
*/
#define ASN__E_cbc(buf, size) (cb((buf), (size), app_key) < 0)
#define ASN__E_CALLBACK(foo) do { \
if(foo) goto cb_failed; \
} while(0)
#define ASN__CALLBACK(buf, size) \
ASN__E_CALLBACK(ASN__E_cbc(buf, size))
#define ASN__CALLBACK2(buf1, size1, buf2, size2) \
ASN__E_CALLBACK(ASN__E_cbc(buf1, size1) || ASN__E_cbc(buf2, size2))
#define ASN__CALLBACK3(buf1, size1, buf2, size2, buf3, size3) \
ASN__E_CALLBACK(ASN__E_cbc(buf1, size1) \
|| ASN__E_cbc(buf2, size2) \
|| ASN__E_cbc(buf3, size3))
#define ASN__TEXT_INDENT(nl, level) do { \
int tmp_level = (level); \
int tmp_nl = ((nl) != 0); \
int tmp_i; \
if(tmp_nl) ASN__CALLBACK("\n", 1); \
if(tmp_level < 0) tmp_level = 0; \
for(tmp_i = 0; tmp_i < tmp_level; tmp_i++) \
ASN__CALLBACK(" ", 4); \
er.encoded += tmp_nl + 4 * tmp_level; \
} while(0)
#define _i_INDENT(nl) do { \
int tmp_i; \
if((nl) && cb("\n", 1, app_key) < 0) \
return -1; \
for(tmp_i = 0; tmp_i < ilevel; tmp_i++) \
if(cb(" ", 4, app_key) < 0) \
return -1; \
} while(0)
/*
* Check stack against overflow, if limit is set.
*/
#define ASN__DEFAULT_STACK_MAX (30000)
static int __attribute__((unused))
ASN__STACK_OVERFLOW_CHECK(asn_codec_ctx_t *ctx) {
if(ctx && ctx->max_stack_size) {
/* ctx MUST be allocated on the stack */
ptrdiff_t usedstack = ((char *)ctx - (char *)&ctx);
if(usedstack > 0) usedstack = -usedstack; /* grows up! */
/* double negative required to avoid int wrap-around */
if(usedstack < -(ptrdiff_t)ctx->max_stack_size) {
ASN_DEBUG("Stack limit %ld reached",
(long)ctx->max_stack_size);
return -1;
}
}
return 0;
}
#ifdef __cplusplus
}
#endif
#endif /* ASN_INTERNAL_H */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/asn_system.h 0000664 0000000 0000000 00000006673 15245442746 0026701 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004, 2007 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
* Miscellaneous system-dependent types.
*/
#ifndef ASN_SYSTEM_H
#define ASN_SYSTEM_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef _BSD_SOURCE
#define _BSD_SOURCE /* for snprintf() on some linux systems */
#endif
#include /* For snprintf(3) */
#include /* For *alloc(3) */
#include /* For memcpy(3) */
#include /* For size_t */
#include /* For LONG_MAX */
#include /* For va_start */
#include /* for offsetof and ptrdiff_t */
#ifdef HAVE_ALLOCA_H
#include /* For alloca(3) */
#endif
#ifdef _WIN32
#include
#define snprintf _snprintf
#define vsnprintf _vsnprintf
/* To avoid linking with ws2_32.lib, here's the definition of ntohl() */
#define sys_ntohl(l) ((((l) << 24) & 0xff000000) \
| (((l) << 8) & 0xff0000) \
| (((l) >> 8) & 0xff00) \
| ((l >> 24) & 0xff))
#ifdef _MSC_VER /* MSVS.Net */
#ifndef __cplusplus
#define inline __inline
#endif
#ifndef ASSUMESTDTYPES /* Standard types have been defined elsewhere */
#define ssize_t SSIZE_T
typedef char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#endif /* ASSUMESTDTYPES */
#define WIN32_LEAN_AND_MEAN
#include
#include
#define isnan _isnan
#define finite _finite
#define copysign _copysign
#define ilogb _logb
#else /* !_MSC_VER */
#include
#endif /* _MSC_VER */
#else /* !_WIN32 */
#if defined(__vxworks)
#include
#else /* !defined(__vxworks) */
#include /* C99 specifies this file */
/*
* 1. Earlier FreeBSD version didn't have ,
* but was present.
* 2. Sun Solaris requires for alloca(3),
* but does not have .
*/
#if (!defined(__FreeBSD__) || !defined(_SYS_INTTYPES_H_))
#if defined(sun)
#include /* For alloca(3) */
#include /* for finite(3) */
#elif defined(__hpux)
#ifdef __GNUC__
#include /* For alloca(3) */
#else /* !__GNUC__ */
#define inline
#endif /* __GNUC__ */
#else
#include /* SUSv2+ and C99 specify this file, for uintXX_t */
#endif /* defined(sun) */
#endif
#include /* for ntohl() */
#define sys_ntohl(foo) ntohl(foo)
#endif /* defined(__vxworks) */
#endif /* _WIN32 */
#if __GNUC__ >= 3
#ifndef GCC_PRINTFLIKE
#define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var)))
#endif
#ifndef GCC_NOTUSED
#define GCC_NOTUSED __attribute__((unused))
#endif
#else
#ifndef GCC_PRINTFLIKE
#define GCC_PRINTFLIKE(fmt,var) /* nothing */
#endif
#ifndef GCC_NOTUSED
#define GCC_NOTUSED
#endif
#endif
/* Figure out if thread safety is requested */
#if !defined(ASN_THREAD_SAFE) && (defined(THREAD_SAFE) || defined(_REENTRANT))
#define ASN_THREAD_SAFE
#endif /* Thread safety */
#ifndef offsetof /* If not defined by */
#define offsetof(s, m) ((ptrdiff_t)&(((s *)0)->m) - (ptrdiff_t)((s *)0))
#endif /* offsetof */
#ifndef MIN /* Suitable for comparing primitive types (integers) */
#if defined(__GNUC__)
#define MIN(a,b) ({ __typeof a _a = a; __typeof b _b = b; \
((_a)<(_b)?(_a):(_b)); })
#else /* !__GNUC__ */
#define MIN(a,b) ((a)<(b)?(a):(b)) /* Unsafe variant */
#endif /* __GNUC__ */
#endif /* MIN */
#endif /* ASN_SYSTEM_H */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/ber_decoder.c 0000664 0000000 0000000 00000016767 15245442746 0026751 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#undef ADVANCE
#define ADVANCE(num_bytes) do { \
size_t num = num_bytes; \
ptr = ((const char *)ptr) + num; \
size -= num; \
consumed_myself += num; \
} while(0)
#undef RETURN
#define RETURN(_code) do { \
asn_dec_rval_t rval; \
rval.code = _code; \
if(opt_ctx) opt_ctx->step = step; /* Save context */ \
if(_code == RC_OK || opt_ctx) \
rval.consumed = consumed_myself; \
else \
rval.consumed = 0; /* Context-free */ \
return rval; \
} while(0)
/*
* The BER decoder of any type.
*/
asn_dec_rval_t
ber_decode(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *type_descriptor,
void **struct_ptr, const void *ptr, size_t size) {
asn_codec_ctx_t s_codec_ctx;
/*
* Stack checker requires that the codec context
* must be allocated on the stack.
*/
if(opt_codec_ctx) {
if(opt_codec_ctx->max_stack_size) {
s_codec_ctx = *opt_codec_ctx;
opt_codec_ctx = &s_codec_ctx;
}
} else {
/* If context is not given, be security-conscious anyway */
memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
opt_codec_ctx = &s_codec_ctx;
}
/*
* Invoke type-specific decoder.
*/
return type_descriptor->ber_decoder(opt_codec_ctx, type_descriptor,
struct_ptr, /* Pointer to the destination structure */
ptr, size, /* Buffer and its size */
0 /* Default tag mode is 0 */
);
}
/*
* Check the set of >> tags matches the definition.
*/
asn_dec_rval_t
ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td, asn_struct_ctx_t *opt_ctx,
const void *ptr, size_t size, int tag_mode, int last_tag_form,
ber_tlv_len_t *last_length, int *opt_tlv_form) {
ssize_t consumed_myself = 0;
ssize_t tag_len;
ssize_t len_len;
ber_tlv_tag_t tlv_tag;
ber_tlv_len_t tlv_len;
ber_tlv_len_t limit_len = -1;
int expect_00_terminators = 0;
int tlv_constr = -1; /* If CHOICE, opt_tlv_form is not given */
int step = opt_ctx ? opt_ctx->step : 0; /* Where we left previously */
int tagno;
/*
* Make sure we didn't exceed the maximum stack size.
*/
if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
RETURN(RC_FAIL);
/*
* So what does all this implicit skip stuff mean?
* Imagine two types,
* A ::= [5] IMPLICIT T
* B ::= [2] EXPLICIT T
* Where T is defined as
* T ::= [4] IMPLICIT SEQUENCE { ... }
*
* Let's say, we are starting to decode type A, given the
* following TLV stream: <5> <0>. What does this mean?
* It means that the type A contains type T which is,
* in turn, empty.
* Remember though, that we are still in A. We cannot
* just pass control to the type T decoder. Why? Because
* the type T decoder expects <4> <0>, not <5> <0>.
* So, we must make sure we are going to receive <5> while
* still in A, then pass control to the T decoder, indicating
* that the tag <4> was implicitly skipped. The decoder of T
* hence will be prepared to treat <4> as valid tag, and decode
* it appropriately.
*/
tagno = step /* Continuing where left previously */
+ (tag_mode==1?-1:0)
;
ASN_DEBUG("ber_check_tags(%s, size=%ld, tm=%d, step=%d, tagno=%d)",
td->name, (long)size, tag_mode, step, tagno);
/* assert(td->tags_count >= 1) May not be the case for CHOICE or ANY */
if(tag_mode == 0 && tagno == td->tags_count) {
/*
* This must be the _untagged_ ANY type,
* which outermost tag isn't known in advance.
* Fetch the tag and length separately.
*/
tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
switch(tag_len) {
case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE);
}
tlv_constr = BER_TLV_CONSTRUCTED(ptr);
len_len = ber_fetch_length(tlv_constr,
(const char *)ptr + tag_len, size - tag_len, &tlv_len);
switch(len_len) {
case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE);
}
ASN_DEBUG("Advancing %ld in ANY case",
(long)(tag_len + len_len));
ADVANCE(tag_len + len_len);
} else {
assert(tagno < td->tags_count); /* At least one loop */
}
for((void)tagno; tagno < td->tags_count; tagno++, step++) {
/*
* Fetch and process T from TLV.
*/
tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
ASN_DEBUG("Fetching tag from {%p,%ld}: "
"len %ld, step %d, tagno %d got %s",
ptr, (long)size,
(long)tag_len, step, tagno,
ber_tlv_tag_string(tlv_tag));
switch(tag_len) {
case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE);
}
tlv_constr = BER_TLV_CONSTRUCTED(ptr);
/*
* If {I}, don't check anything.
* If {I,B,C}, check B and C unless we're at I.
*/
if(tag_mode != 0 && step == 0) {
/*
* We don't expect tag to match here.
* It's just because we don't know how the tag
* is supposed to look like.
*/
} else {
assert(tagno >= 0); /* Guaranteed by the code above */
if(tlv_tag != td->tags[tagno]) {
/*
* Unexpected tag. Too bad.
*/
ASN_DEBUG("Expected: %s, "
"expectation failed (tn=%d, tm=%d)",
ber_tlv_tag_string(td->tags[tagno]),
tagno, tag_mode
);
RETURN(RC_FAIL);
}
}
/*
* Attention: if there are more tags expected,
* ensure that the current tag is presented
* in constructed form (it contains other tags!).
* If this one is the last one, check that the tag form
* matches the one given in descriptor.
*/
if(tagno < (td->tags_count - 1)) {
if(tlv_constr == 0) {
ASN_DEBUG("tlv_constr = %d, expfail",
tlv_constr);
RETURN(RC_FAIL);
}
} else {
if(last_tag_form != tlv_constr
&& last_tag_form != -1) {
ASN_DEBUG("last_tag_form %d != %d",
last_tag_form, tlv_constr);
RETURN(RC_FAIL);
}
}
/*
* Fetch and process L from TLV.
*/
len_len = ber_fetch_length(tlv_constr,
(const char *)ptr + tag_len, size - tag_len, &tlv_len);
ASN_DEBUG("Fetching len = %ld", (long)len_len);
switch(len_len) {
case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE);
}
/*
* FIXME
* As of today, the chain of tags
* must either contain several indefinite length TLVs,
* or several definite length ones.
* No mixing is allowed.
*/
if(tlv_len == -1) {
/*
* Indefinite length.
*/
if(limit_len == -1) {
expect_00_terminators++;
} else {
ASN_DEBUG("Unexpected indefinite length "
"in a chain of definite lengths");
RETURN(RC_FAIL);
}
ADVANCE(tag_len + len_len);
continue;
} else {
if(expect_00_terminators) {
ASN_DEBUG("Unexpected definite length "
"in a chain of indefinite lengths");
RETURN(RC_FAIL);
}
}
/*
* Check that multiple TLVs specify ever decreasing length,
* which is consistent.
*/
if(limit_len == -1) {
limit_len = tlv_len + tag_len + len_len;
if(limit_len < 0) {
/* Too great tlv_len value? */
RETURN(RC_FAIL);
}
} else if(limit_len != tlv_len + tag_len + len_len) {
/*
* Inner TLV specifies length which is inconsistent
* with the outer TLV's length value.
*/
ASN_DEBUG("Outer TLV is %ld and inner is %ld",
(long)limit_len, (long)tlv_len);
RETURN(RC_FAIL);
}
ADVANCE(tag_len + len_len);
limit_len -= (tag_len + len_len);
if((ssize_t)size > limit_len) {
/*
* Make sure that we won't consume more bytes
* from the parent frame than the inferred limit.
*/
size = limit_len;
}
}
if(opt_tlv_form)
*opt_tlv_form = tlv_constr;
if(expect_00_terminators)
*last_length = -expect_00_terminators;
else
*last_length = tlv_len;
RETURN(RC_OK);
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/ber_decoder.h 0000664 0000000 0000000 00000003777 15245442746 0026753 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _BER_DECODER_H_
#define _BER_DECODER_H_
#include
#ifdef __cplusplus
extern "C" {
#endif
struct asn_TYPE_descriptor_s; /* Forward declaration */
struct asn_codec_ctx_s; /* Forward declaration */
/*
* The BER decoder of any type.
* This function may be invoked directly from the application.
* The der_encode() function (der_encoder.h) is an opposite to ber_decode().
*/
asn_dec_rval_t ber_decode(struct asn_codec_ctx_s *opt_codec_ctx,
struct asn_TYPE_descriptor_s *type_descriptor,
void **struct_ptr, /* Pointer to a target structure's pointer */
const void *buffer, /* Data to be decoded */
size_t size /* Size of that buffer */
);
/*
* Type of generic function which decodes the byte stream into the structure.
*/
typedef asn_dec_rval_t (ber_type_decoder_f)(
struct asn_codec_ctx_s *opt_codec_ctx,
struct asn_TYPE_descriptor_s *type_descriptor,
void **struct_ptr, const void *buf_ptr, size_t size,
int tag_mode);
/*******************************
* INTERNALLY USEFUL FUNCTIONS *
*******************************/
/*
* Check that all tags correspond to the type definition (as given in head).
* On return, last_length would contain either a non-negative length of the
* value part of the last TLV, or the negative number of expected
* "end of content" sequences. The number may only be negative if the
* head->last_tag_form is non-zero.
*/
asn_dec_rval_t ber_check_tags(
struct asn_codec_ctx_s *opt_codec_ctx, /* codec options */
struct asn_TYPE_descriptor_s *type_descriptor,
asn_struct_ctx_t *opt_ctx, /* saved decoding context */
const void *ptr, size_t size,
int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */
int last_tag_form, /* {-1,0:1}: any, primitive, constr */
ber_tlv_len_t *last_length,
int *opt_tlv_form /* optional tag form */
);
#ifdef __cplusplus
}
#endif
#endif /* _BER_DECODER_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/ber_tlv_length.c 0000664 0000000 0000000 00000007310 15245442746 0027472 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include
ssize_t
ber_fetch_length(int _is_constructed, const void *bufptr, size_t size,
ber_tlv_len_t *len_r) {
const uint8_t *buf = (const uint8_t *)bufptr;
unsigned oct;
if(size == 0)
return 0; /* Want more */
oct = *(const uint8_t *)buf;
if((oct & 0x80) == 0) {
/*
* Short definite length.
*/
*len_r = oct; /* & 0x7F */
return 1;
} else {
ber_tlv_len_t len;
size_t skipped;
if(_is_constructed && oct == 0x80) {
*len_r = -1; /* Indefinite length */
return 1;
}
if(oct == 0xff) {
/* Reserved in standard for future use. */
return -1;
}
oct &= 0x7F; /* Leave only the 7 LS bits */
for(len = 0, buf++, skipped = 1;
oct && (++skipped <= size); buf++, oct--) {
len = (len << 8) | *buf;
if(len < 0
|| (len >> ((8 * sizeof(len)) - 8) && oct > 1)) {
/*
* Too large length value.
*/
return -1;
}
}
if(oct == 0) {
ber_tlv_len_t lenplusepsilon = (size_t)len + 1024;
/*
* Here length may be very close or equal to 2G.
* However, the arithmetics used in some decoders
* may add some (small) quantities to the length,
* to check the resulting value against some limits.
* This may result in integer wrap-around, which
* we try to avoid by checking it earlier here.
*/
if(lenplusepsilon < 0) {
/* Too large length value */
return -1;
}
*len_r = len;
return skipped;
}
return 0; /* Want more */
}
}
ssize_t
ber_skip_length(asn_codec_ctx_t *opt_codec_ctx,
int _is_constructed, const void *ptr, size_t size) {
ber_tlv_len_t vlen; /* Length of V in TLV */
ssize_t tl; /* Length of L in TLV */
ssize_t ll; /* Length of L in TLV */
size_t skip;
/*
* Make sure we didn't exceed the maximum stack size.
*/
if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
return -1;
/*
* Determine the size of L in TLV.
*/
ll = ber_fetch_length(_is_constructed, ptr, size, &vlen);
if(ll <= 0) return ll;
/*
* Definite length.
*/
if(vlen >= 0) {
skip = ll + vlen;
if(skip > size)
return 0; /* Want more */
return skip;
}
/*
* Indefinite length!
*/
ASN_DEBUG("Skipping indefinite length");
for(skip = ll, ptr = ((const char *)ptr) + ll, size -= ll;;) {
ber_tlv_tag_t tag;
/* Fetch the tag */
tl = ber_fetch_tag(ptr, size, &tag);
if(tl <= 0) return tl;
ll = ber_skip_length(opt_codec_ctx,
BER_TLV_CONSTRUCTED(ptr),
((const char *)ptr) + tl, size - tl);
if(ll <= 0) return ll;
skip += tl + ll;
/*
* This may be the end of the indefinite length structure,
* two consecutive 0 octets.
* Check if it is true.
*/
if(((const uint8_t *)ptr)[0] == 0
&& ((const uint8_t *)ptr)[1] == 0)
return skip;
ptr = ((const char *)ptr) + tl + ll;
size -= tl + ll;
}
/* UNREACHABLE */
}
size_t
der_tlv_length_serialize(ber_tlv_len_t len, void *bufp, size_t size) {
size_t required_size; /* Size of len encoding */
uint8_t *buf = (uint8_t *)bufp;
uint8_t *end;
size_t i;
if(len <= 127) {
/* Encoded in 1 octet */
if(size) *buf = (uint8_t)len;
return 1;
}
/*
* Compute the size of the subsequent bytes.
*/
for(required_size = 1, i = 8; i < 8 * sizeof(len); i += 8) {
if(len >> i)
required_size++;
else
break;
}
if(size <= required_size)
return required_size + 1;
*buf++ = (uint8_t)(0x80 | required_size); /* Length of the encoding */
/*
* Produce the len encoding, space permitting.
*/
end = buf + required_size;
for(i -= 8; buf < end; i -= 8, buf++)
*buf = (uint8_t)(len >> i);
return required_size + 1;
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/ber_tlv_length.h 0000664 0000000 0000000 00000002775 15245442746 0027511 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _BER_TLV_LENGTH_H_
#define _BER_TLV_LENGTH_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef ssize_t ber_tlv_len_t;
/*
* This function tries to fetch the length of the BER TLV value and place it
* in *len_r.
* RETURN VALUES:
* 0: More data expected than bufptr contains.
* -1: Fatal error deciphering length.
* >0: Number of bytes used from bufptr.
* On return with >0, len_r is constrained as -1..MAX, where -1 mean
* that the value is of indefinite length.
*/
ssize_t ber_fetch_length(int _is_constructed, const void *bufptr, size_t size,
ber_tlv_len_t *len_r);
/*
* This function expects bufptr to be positioned over L in TLV.
* It returns number of bytes occupied by L and V together, suitable
* for skipping. The function properly handles indefinite length.
* RETURN VALUES:
* Standard {-1,0,>0} convention.
*/
ssize_t ber_skip_length(
struct asn_codec_ctx_s *opt_codec_ctx, /* optional context */
int _is_constructed, const void *bufptr, size_t size);
/*
* This function serializes the length (L from TLV) in DER format.
* It always returns number of bytes necessary to represent the length,
* it is a caller's responsibility to check the return value
* against the supplied buffer's size.
*/
size_t der_tlv_length_serialize(ber_tlv_len_t len, void *bufptr, size_t size);
#ifdef __cplusplus
}
#endif
#endif /* _BER_TLV_LENGTH_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/ber_tlv_tag.c 0000664 0000000 0000000 00000006156 15245442746 0026773 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include
ssize_t
ber_fetch_tag(const void *ptr, size_t size, ber_tlv_tag_t *tag_r) {
ber_tlv_tag_t val;
ber_tlv_tag_t tclass;
size_t skipped;
if(size == 0)
return 0;
val = *(const uint8_t *)ptr;
tclass = (val >> 6);
if((val &= 0x1F) != 0x1F) {
/*
* Simple form: everything encoded in a single octet.
* Tag Class is encoded using two least significant bits.
*/
*tag_r = (val << 2) | tclass;
return 1;
}
/*
* Each octet contains 7 bits of useful information.
* The MSB is 0 if it is the last octet of the tag.
*/
for(val = 0, ptr = ((const char *)ptr) + 1, skipped = 2;
skipped <= size;
ptr = ((const char *)ptr) + 1, skipped++) {
unsigned int oct = *(const uint8_t *)ptr;
if(oct & 0x80) {
val = (val << 7) | (oct & 0x7F);
/*
* Make sure there are at least 9 bits spare
* at the MS side of a value.
*/
if(val >> ((8 * sizeof(val)) - 9)) {
/*
* We would not be able to accomodate
* any more tag bits.
*/
return -1;
}
} else {
val = (val << 7) | oct;
*tag_r = (val << 2) | tclass;
return skipped;
}
}
return 0; /* Want more */
}
ssize_t
ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *f) {
char buf[sizeof("[APPLICATION ]") + 32];
ssize_t ret;
ret = ber_tlv_tag_snprint(tag, buf, sizeof(buf));
if(ret >= (ssize_t)sizeof(buf) || ret < 2) {
errno = EPERM;
return -1;
}
return fwrite(buf, 1, ret, f);
}
ssize_t
ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t size) {
char *type = 0;
int ret;
switch(tag & 0x3) {
case ASN_TAG_CLASS_UNIVERSAL: type = "UNIVERSAL "; break;
case ASN_TAG_CLASS_APPLICATION: type = "APPLICATION "; break;
case ASN_TAG_CLASS_CONTEXT: type = ""; break;
case ASN_TAG_CLASS_PRIVATE: type = "PRIVATE "; break;
}
ret = snprintf(buf, size, "[%s%u]", type, ((unsigned)tag) >> 2);
if(ret <= 0 && size) buf[0] = '\0'; /* against broken libc's */
return ret;
}
char *
ber_tlv_tag_string(ber_tlv_tag_t tag) {
static char buf[sizeof("[APPLICATION ]") + 32];
(void)ber_tlv_tag_snprint(tag, buf, sizeof(buf));
return buf;
}
size_t
ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufp, size_t size) {
int tclass = BER_TAG_CLASS(tag);
ber_tlv_tag_t tval = BER_TAG_VALUE(tag);
uint8_t *buf = (uint8_t *)bufp;
uint8_t *end;
size_t required_size;
size_t i;
if(tval <= 30) {
/* Encoded in 1 octet */
if(size) buf[0] = (tclass << 6) | tval;
return 1;
} else if(size) {
*buf++ = (tclass << 6) | 0x1F;
size--;
}
/*
* Compute the size of the subsequent bytes.
*/
for(required_size = 1, i = 7; i < 8 * sizeof(tval); i += 7) {
if(tval >> i)
required_size++;
else
break;
}
if(size < required_size)
return required_size + 1;
/*
* Fill in the buffer, space permitting.
*/
end = buf + required_size - 1;
for(i -= 7; buf < end; i -= 7, buf++)
*buf = 0x80 | ((tval >> i) & 0x7F);
*buf = (tval & 0x7F); /* Last octet without high bit */
return required_size + 1;
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/ber_tlv_tag.h 0000664 0000000 0000000 00000003454 15245442746 0026776 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _BER_TLV_TAG_H_
#define _BER_TLV_TAG_H_
#ifdef __cplusplus
extern "C" {
#endif
enum asn_tag_class {
ASN_TAG_CLASS_UNIVERSAL = 0, /* 0b00 */
ASN_TAG_CLASS_APPLICATION = 1, /* 0b01 */
ASN_TAG_CLASS_CONTEXT = 2, /* 0b10 */
ASN_TAG_CLASS_PRIVATE = 3 /* 0b11 */
};
typedef unsigned ber_tlv_tag_t; /* BER TAG from Tag-Length-Value */
/*
* Tag class is encoded together with tag value for optimization purposes.
*/
#define BER_TAG_CLASS(tag) ((tag) & 0x3)
#define BER_TAG_VALUE(tag) ((tag) >> 2)
#define BER_TLV_CONSTRUCTED(tagptr) (((*(const uint8_t *)tagptr)&0x20)?1:0)
#define BER_TAGS_EQUAL(tag1, tag2) ((tag1) == (tag2))
/*
* Several functions for printing the TAG in the canonical form
* (i.e. "[PRIVATE 0]").
* Return values correspond to their libc counterparts (if any).
*/
ssize_t ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t buflen);
ssize_t ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *);
char *ber_tlv_tag_string(ber_tlv_tag_t tag);
/*
* This function tries to fetch the tag from the input stream.
* RETURN VALUES:
* 0: More data expected than bufptr contains.
* -1: Fatal error deciphering tag.
* >0: Number of bytes used from bufptr. tag_r will contain the tag.
*/
ssize_t ber_fetch_tag(const void *bufptr, size_t size, ber_tlv_tag_t *tag_r);
/*
* This function serializes the tag (T from TLV) in BER format.
* It always returns number of bytes necessary to represent the tag,
* it is a caller's responsibility to check the return value
* against the supplied buffer's size.
*/
size_t ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufptr, size_t size);
#ifdef __cplusplus
}
#endif
#endif /* _BER_TLV_TAG_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/constr_CHOICE.c 0000664 0000000 0000000 00000070062 15245442746 0027022 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include
/*
* Number of bytes left for this structure.
* (ctx->left) indicates the number of bytes _transferred_ for the structure.
* (size) contains the number of bytes in the buffer passed.
*/
#define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left)
/*
* If the subprocessor function returns with an indication that it wants
* more data, it may well be a fatal decoding problem, because the
* size is constrained by the 's L, even if the buffer size allows
* reading more data.
* For example, consider the buffer containing the following TLVs:
* ...
* The TLV length clearly indicates that one byte is expected in V, but
* if the V processor returns with "want more data" even if the buffer
* contains way more data than the V processor have seen.
*/
#define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size)
/*
* This macro "eats" the part of the buffer which is definitely "consumed",
* i.e. was correctly converted into local representation or rightfully skipped.
*/
#undef ADVANCE
#define ADVANCE(num_bytes) do { \
size_t num = num_bytes; \
ptr = ((const char *)ptr) + num;\
size -= num; \
if(ctx->left >= 0) \
ctx->left -= num; \
consumed_myself += num; \
} while(0)
/*
* Switch to the next phase of parsing.
*/
#undef NEXT_PHASE
#define NEXT_PHASE(ctx) do { \
ctx->phase++; \
ctx->step = 0; \
} while(0)
/*
* Return a standardized complex structure.
*/
#undef RETURN
#define RETURN(_code) do { \
rval.code = _code; \
rval.consumed = consumed_myself;\
return rval; \
} while(0)
/*
* See the definitions.
*/
static int _fetch_present_idx(const void *struct_ptr, int off, int size);
static void _set_present_idx(void *sptr, int offset, int size, int pres);
/*
* Tags are canonically sorted in the tag to member table.
*/
static int
_search4tag(const void *ap, const void *bp) {
const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
int a_class = BER_TAG_CLASS(a->el_tag);
int b_class = BER_TAG_CLASS(b->el_tag);
if(a_class == b_class) {
ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
if(a_value == b_value)
return 0;
else if(a_value < b_value)
return -1;
else
return 1;
} else if(a_class < b_class) {
return -1;
} else {
return 1;
}
}
/*
* The decoder of the CHOICE type.
*/
asn_dec_rval_t
CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
/*
* Bring closer parts of structure description.
*/
asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
asn_TYPE_member_t *elements = td->elements;
/*
* Parts of the structure being constructed.
*/
void *st = *struct_ptr; /* Target structure. */
asn_struct_ctx_t *ctx; /* Decoder context */
ber_tlv_tag_t tlv_tag; /* T from TLV */
ssize_t tag_len; /* Length of TLV's T */
asn_dec_rval_t rval; /* Return code from subparsers */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
ASN_DEBUG("Decoding %s as CHOICE", td->name);
/*
* Create the target structure if it is not present already.
*/
if(st == 0) {
st = *struct_ptr = CALLOC(1, specs->struct_size);
if(st == 0) {
RETURN(RC_FAIL);
}
}
/*
* Restore parsing context.
*/
ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
/*
* Start to parse where left previously
*/
switch(ctx->phase) {
case 0:
/*
* PHASE 0.
* Check that the set of tags associated with given structure
* perfectly fits our expectations.
*/
if(tag_mode || td->tags_count) {
rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
tag_mode, -1, &ctx->left, 0);
if(rval.code != RC_OK) {
ASN_DEBUG("%s tagging check failed: %d",
td->name, rval.code);
return rval;
}
if(ctx->left >= 0) {
/* ?Substracted below! */
ctx->left += rval.consumed;
}
ADVANCE(rval.consumed);
} else {
ctx->left = -1;
}
NEXT_PHASE(ctx);
ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
(long)ctx->left, (long)size);
/* Fall through */
case 1:
/*
* Fetch the T from TLV.
*/
tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
ASN_DEBUG("In %s CHOICE tag length %d", td->name, (int)tag_len);
switch(tag_len) {
case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
/* Fall through */
case -1: RETURN(RC_FAIL);
}
do {
const asn_TYPE_tag2member_t *t2m;
asn_TYPE_tag2member_t key;
key.el_tag = tlv_tag;
t2m = (const asn_TYPE_tag2member_t *)bsearch(&key,
specs->tag2el, specs->tag2el_count,
sizeof(specs->tag2el[0]), _search4tag);
if(t2m) {
/*
* Found the element corresponding to the tag.
*/
NEXT_PHASE(ctx);
ctx->step = t2m->el_no;
break;
} else if(specs->ext_start == -1) {
ASN_DEBUG("Unexpected tag %s "
"in non-extensible CHOICE %s",
ber_tlv_tag_string(tlv_tag), td->name);
RETURN(RC_FAIL);
} else {
/* Skip this tag */
ssize_t skip;
ASN_DEBUG("Skipping unknown tag %s",
ber_tlv_tag_string(tlv_tag));
skip = ber_skip_length(opt_codec_ctx,
BER_TLV_CONSTRUCTED(ptr),
(const char *)ptr + tag_len,
LEFT - tag_len);
switch(skip) {
case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
/* Fall through */
case -1: RETURN(RC_FAIL);
}
ADVANCE(skip + tag_len);
RETURN(RC_OK);
}
} while(0);
case 2:
/*
* PHASE 2.
* Read in the element.
*/
do {
asn_TYPE_member_t *elm;/* CHOICE's element */
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
elm = &elements[ctx->step];
/*
* Compute the position of the member inside a structure,
* and also a type of containment (it may be contained
* as pointer or using inline inclusion).
*/
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
memb_ptr2 = (void **)((char *)st + elm->memb_offset);
} else {
/*
* A pointer to a pointer
* holding the start of the structure
*/
memb_ptr = (char *)st + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
/* Set presence to be able to free it properly at any time */
_set_present_idx(st, specs->pres_offset,
specs->pres_size, ctx->step + 1);
/*
* Invoke the member fetch routine according to member's type
*/
rval = elm->type->ber_decoder(opt_codec_ctx, elm->type,
memb_ptr2, ptr, LEFT, elm->tag_mode);
switch(rval.code) {
case RC_OK:
break;
case RC_WMORE: /* More data expected */
if(!SIZE_VIOLATION) {
ADVANCE(rval.consumed);
RETURN(RC_WMORE);
}
RETURN(RC_FAIL);
case RC_FAIL: /* Fatal error */
RETURN(rval.code);
} /* switch(rval) */
ADVANCE(rval.consumed);
} while(0);
NEXT_PHASE(ctx);
/* Fall through */
case 3:
ASN_DEBUG("CHOICE %s Leftover: %ld, size = %ld, tm=%d, tc=%d",
td->name, (long)ctx->left, (long)size,
tag_mode, td->tags_count);
if(ctx->left > 0) {
/*
* The type must be fully decoded
* by the CHOICE member-specific decoder.
*/
RETURN(RC_FAIL);
}
if(ctx->left == -1
&& !(tag_mode || td->tags_count)) {
/*
* This is an untagged CHOICE.
* It doesn't contain nothing
* except for the member itself, including all its tags.
* The decoding is completed.
*/
NEXT_PHASE(ctx);
break;
}
/*
* Read in the "end of data chunks"'s.
*/
while(ctx->left < 0) {
ssize_t tl;
tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
switch(tl) {
case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
/* Fall through */
case -1: RETURN(RC_FAIL);
}
/*
* Expected <0><0>...
*/
if(((const uint8_t *)ptr)[0] == 0) {
if(LEFT < 2) {
if(SIZE_VIOLATION)
RETURN(RC_FAIL);
else
RETURN(RC_WMORE);
} else if(((const uint8_t *)ptr)[1] == 0) {
/*
* Correctly finished with <0><0>.
*/
ADVANCE(2);
ctx->left++;
continue;
}
} else {
ASN_DEBUG("Unexpected continuation in %s",
td->name);
RETURN(RC_FAIL);
}
/* UNREACHABLE */
}
NEXT_PHASE(ctx);
case 4:
/* No meaningful work here */
break;
}
RETURN(RC_OK);
}
asn_enc_rval_t
CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
asn_TYPE_member_t *elm; /* CHOICE element */
asn_enc_rval_t erval;
void *memb_ptr;
size_t computed_size = 0;
int present;
if(!sptr) ASN__ENCODE_FAILED;
ASN_DEBUG("%s %s as CHOICE",
cb?"Encoding":"Estimating", td->name);
present = _fetch_present_idx(sptr,
specs->pres_offset, specs->pres_size);
/*
* If the structure was not initialized, it cannot be encoded:
* can't deduce what to encode in the choice type.
*/
if(present <= 0 || present > td->elements_count) {
if(present == 0 && td->elements_count == 0) {
/* The CHOICE is empty?! */
erval.encoded = 0;
ASN__ENCODED_OK(erval);
}
ASN__ENCODE_FAILED;
}
/*
* Seek over the present member of the structure.
*/
elm = &td->elements[present-1];
if(elm->flags & ATF_POINTER) {
memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
if(memb_ptr == 0) {
if(elm->optional) {
erval.encoded = 0;
ASN__ENCODED_OK(erval);
}
/* Mandatory element absent */
ASN__ENCODE_FAILED;
}
} else {
memb_ptr = (void *)((char *)sptr + elm->memb_offset);
}
/*
* If the CHOICE itself is tagged EXPLICIT:
* T ::= [2] EXPLICIT CHOICE { ... }
* Then emit the appropriate tags.
*/
if(tag_mode == 1 || td->tags_count) {
/*
* For this, we need to pre-compute the member.
*/
ssize_t ret;
/* Encode member with its tag */
erval = elm->type->der_encoder(elm->type, memb_ptr,
elm->tag_mode, elm->tag, 0, 0);
if(erval.encoded == -1)
return erval;
/* Encode CHOICE with parent or my own tag */
ret = der_write_tags(td, erval.encoded, tag_mode, 1, tag,
cb, app_key);
if(ret == -1)
ASN__ENCODE_FAILED;
computed_size += ret;
}
/*
* Encode the single underlying member.
*/
erval = elm->type->der_encoder(elm->type, memb_ptr,
elm->tag_mode, elm->tag, cb, app_key);
if(erval.encoded == -1)
return erval;
ASN_DEBUG("Encoded CHOICE member in %ld bytes (+%ld)",
(long)erval.encoded, (long)computed_size);
erval.encoded += computed_size;
return erval;
}
ber_tlv_tag_t
CHOICE_outmost_tag(const asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber_tlv_tag_t tag) {
asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
int present;
assert(tag_mode == 0); (void)tag_mode;
assert(tag == 0); (void)tag;
/*
* Figure out which CHOICE element is encoded.
*/
present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
if(present > 0 || present <= td->elements_count) {
const asn_TYPE_member_t *elm = &td->elements[present-1];
const void *memb_ptr;
if(elm->flags & ATF_POINTER) {
memb_ptr = *(const void * const *)
((const char *)ptr + elm->memb_offset);
} else {
memb_ptr = (const void *)
((const char *)ptr + elm->memb_offset);
}
return asn_TYPE_outmost_tag(elm->type, memb_ptr,
elm->tag_mode, elm->tag);
} else {
return (ber_tlv_tag_t)-1;
}
}
int
CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
int present;
if(!sptr) {
ASN__CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
/*
* Figure out which CHOICE element is encoded.
*/
present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
if(present > 0 && present <= td->elements_count) {
asn_TYPE_member_t *elm = &td->elements[present-1];
const void *memb_ptr;
if(elm->flags & ATF_POINTER) {
memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
if(!memb_ptr) {
if(elm->optional)
return 0;
ASN__CTFAIL(app_key, td, sptr,
"%s: mandatory CHOICE element %s absent (%s:%d)",
td->name, elm->name, __FILE__, __LINE__);
return -1;
}
} else {
memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
}
if(elm->memb_constraints) {
return elm->memb_constraints(elm->type, memb_ptr,
ctfailcb, app_key);
} else {
int ret = elm->type->check_constraints(elm->type,
memb_ptr, ctfailcb, app_key);
/*
* Cannot inherit it eralier:
* need to make sure we get the updated version.
*/
elm->memb_constraints = elm->type->check_constraints;
return ret;
}
} else {
ASN__CTFAIL(app_key, td, sptr,
"%s: no CHOICE element given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
}
#undef XER_ADVANCE
#define XER_ADVANCE(num_bytes) do { \
size_t num = num_bytes; \
buf_ptr = (const void *)(((const char *)buf_ptr) + num); \
size -= num; \
consumed_myself += num; \
} while(0)
/*
* Decode the XER (XML) data.
*/
asn_dec_rval_t
CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **struct_ptr, const char *opt_mname,
const void *buf_ptr, size_t size) {
/*
* Bring closer parts of structure description.
*/
asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
/*
* Parts of the structure being constructed.
*/
void *st = *struct_ptr; /* Target structure. */
asn_struct_ctx_t *ctx; /* Decoder context */
asn_dec_rval_t rval; /* Return value of a decoder */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
int edx; /* Element index */
/*
* Create the target structure if it is not present already.
*/
if(st == 0) {
st = *struct_ptr = CALLOC(1, specs->struct_size);
if(st == 0) RETURN(RC_FAIL);
}
/*
* Restore parsing context.
*/
ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
if(ctx->phase == 0 && !*xml_tag)
ctx->phase = 1; /* Skip the outer tag checking phase */
/*
* Phases of XER/XML processing:
* Phase 0: Check that the opening tag matches our expectations.
* Phase 1: Processing body and reacting on closing tag.
* Phase 2: Processing inner type.
* Phase 3: Only waiting for closing tag.
* Phase 4: Skipping unknown extensions.
* Phase 5: PHASED OUT
*/
for(edx = ctx->step; ctx->phase <= 4;) {
pxer_chunk_type_e ch_type; /* XER chunk type */
ssize_t ch_size; /* Chunk size */
xer_check_tag_e tcv; /* Tag check value */
asn_TYPE_member_t *elm;
/*
* Go inside the member.
*/
if(ctx->phase == 2) {
asn_dec_rval_t tmprval;
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
elm = &td->elements[edx];
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
memb_ptr2 = (void **)((char *)st
+ elm->memb_offset);
} else {
memb_ptr = (char *)st + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
/* Start/Continue decoding the inner member */
tmprval = elm->type->xer_decoder(opt_codec_ctx,
elm->type, memb_ptr2, elm->name,
buf_ptr, size);
XER_ADVANCE(tmprval.consumed);
ASN_DEBUG("XER/CHOICE: itdf: [%s] code=%d",
elm->type->name, tmprval.code);
if(tmprval.code != RC_OK)
RETURN(tmprval.code);
assert(_fetch_present_idx(st,
specs->pres_offset, specs->pres_size) == 0);
/* Record what we've got */
_set_present_idx(st,
specs->pres_offset, specs->pres_size, edx + 1);
ctx->phase = 3;
/* Fall through */
}
/* No need to wait for closing tag; special mode. */
if(ctx->phase == 3 && !*xml_tag) {
ctx->phase = 5; /* Phase out */
RETURN(RC_OK);
}
/*
* Get the next part of the XML stream.
*/
ch_size = xer_next_token(&ctx->context, buf_ptr, size, &ch_type);
if(ch_size == -1) {
RETURN(RC_FAIL);
} else {
switch(ch_type) {
case PXER_WMORE:
RETURN(RC_WMORE);
case PXER_COMMENT: /* Got XML comment */
case PXER_TEXT: /* Ignore free-standing text */
XER_ADVANCE(ch_size); /* Skip silently */
continue;
case PXER_TAG:
break; /* Check the rest down there */
}
}
tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
ASN_DEBUG("XER/CHOICE checked [%c%c%c%c] vs [%s], tcv=%d",
ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
xml_tag, tcv);
/* Skip the extensions section */
if(ctx->phase == 4) {
ASN_DEBUG("skip_unknown(%d, %ld)",
tcv, (long)ctx->left);
switch(xer_skip_unknown(tcv, &ctx->left)) {
case -1:
ctx->phase = 5;
RETURN(RC_FAIL);
continue;
case 1:
ctx->phase = 3;
/* Fall through */
case 0:
XER_ADVANCE(ch_size);
continue;
case 2:
ctx->phase = 3;
break;
}
}
switch(tcv) {
case XCT_BOTH:
break; /* No CHOICE? */
case XCT_CLOSING:
if(ctx->phase != 3)
break;
XER_ADVANCE(ch_size);
ctx->phase = 5; /* Phase out */
RETURN(RC_OK);
case XCT_OPENING:
if(ctx->phase == 0) {
XER_ADVANCE(ch_size);
ctx->phase = 1; /* Processing body phase */
continue;
}
/* Fall through */
case XCT_UNKNOWN_OP:
case XCT_UNKNOWN_BO:
if(ctx->phase != 1)
break; /* Really unexpected */
/*
* Search which inner member corresponds to this tag.
*/
for(edx = 0; edx < td->elements_count; edx++) {
elm = &td->elements[edx];
tcv = xer_check_tag(buf_ptr,ch_size,elm->name);
switch(tcv) {
case XCT_BOTH:
case XCT_OPENING:
/*
* Process this member.
*/
ctx->step = edx;
ctx->phase = 2;
break;
case XCT_UNKNOWN_OP:
case XCT_UNKNOWN_BO:
continue;
default:
edx = td->elements_count;
break; /* Phase out */
}
break;
}
if(edx != td->elements_count)
continue;
/* It is expected extension */
if(specs->ext_start != -1) {
ASN_DEBUG("Got anticipated extension");
/*
* Check for (XCT_BOTH or XCT_UNKNOWN_BO)
* By using a mask. Only record a pure
* tags.
*/
if(tcv & XCT_CLOSING) {
/* Found without body */
ctx->phase = 3; /* Terminating */
} else {
ctx->left = 1;
ctx->phase = 4; /* Skip ...'s */
}
XER_ADVANCE(ch_size);
continue;
}
/* Fall through */
default:
break;
}
ASN_DEBUG("Unexpected XML tag [%c%c%c%c] in CHOICE [%s]"
" (ph=%d, tag=%s)",
ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
td->name, ctx->phase, xml_tag);
break;
}
ctx->phase = 5; /* Phase out, just in case */
RETURN(RC_FAIL);
}
asn_enc_rval_t
CHOICE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_CHOICE_specifics_t *specs=(asn_CHOICE_specifics_t *)td->specifics;
asn_enc_rval_t er;
int present;
if(!sptr)
ASN__ENCODE_FAILED;
/*
* Figure out which CHOICE element is encoded.
*/
present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
if(present <= 0 || present > td->elements_count) {
ASN__ENCODE_FAILED;
} else {
asn_enc_rval_t tmper;
asn_TYPE_member_t *elm = &td->elements[present-1];
void *memb_ptr;
const char *mname = elm->name;
unsigned int mlen = strlen(mname);
if(elm->flags & ATF_POINTER) {
memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
if(!memb_ptr) ASN__ENCODE_FAILED;
} else {
memb_ptr = (void *)((char *)sptr + elm->memb_offset);
}
er.encoded = 0;
if(!(flags & XER_F_CANONICAL)) ASN__TEXT_INDENT(1, ilevel);
ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
tmper = elm->type->xer_encoder(elm->type, memb_ptr,
ilevel + 1, flags, cb, app_key);
if(tmper.encoded == -1) return tmper;
ASN__CALLBACK3("", 2, mname, mlen, ">", 1);
er.encoded += 5 + (2 * mlen) + tmper.encoded;
}
if(!(flags & XER_F_CANONICAL)) ASN__TEXT_INDENT(1, ilevel - 1);
ASN__ENCODED_OK(er);
cb_failed:
ASN__ENCODE_FAILED;
}
asn_dec_rval_t
CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
asn_dec_rval_t rv;
asn_per_constraint_t *ct;
asn_TYPE_member_t *elm; /* CHOICE's element */
void *memb_ptr;
void **memb_ptr2;
void *st = *sptr;
int value;
if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
ASN__DECODE_FAILED;
/*
* Create the target structure if it is not present already.
*/
if(!st) {
st = *sptr = CALLOC(1, specs->struct_size);
if(!st) ASN__DECODE_FAILED;
}
if(constraints) ct = &constraints->value;
else if(td->per_constraints) ct = &td->per_constraints->value;
else ct = 0;
if(ct && ct->flags & APC_EXTENSIBLE) {
value = per_get_few_bits(pd, 1);
if(value < 0) ASN__DECODE_STARVED;
if(value) ct = 0; /* Not restricted */
}
if(ct && ct->range_bits >= 0) {
value = per_get_few_bits(pd, ct->range_bits);
if(value < 0) ASN__DECODE_STARVED;
ASN_DEBUG("CHOICE %s got index %d in range %d",
td->name, value, ct->range_bits);
if(value > ct->upper_bound)
ASN__DECODE_FAILED;
} else {
if(specs->ext_start == -1)
ASN__DECODE_FAILED;
value = uper_get_nsnnwn(pd);
if(value < 0) ASN__DECODE_STARVED;
value += specs->ext_start;
if(value >= td->elements_count)
ASN__DECODE_FAILED;
}
/* Adjust if canonical order is different from natural order */
if(specs->canonical_order)
value = specs->canonical_order[value];
/* Set presence to be able to free it later */
_set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1);
elm = &td->elements[value];
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
memb_ptr2 = (void **)((char *)st + elm->memb_offset);
} else {
memb_ptr = (char *)st + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
if(ct && ct->range_bits >= 0) {
rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
elm->per_constraints, memb_ptr2, pd);
} else {
rv = uper_open_type_get(opt_codec_ctx, elm->type,
elm->per_constraints, memb_ptr2, pd);
}
if(rv.code != RC_OK)
ASN_DEBUG("Failed to decode %s in %s (CHOICE) %d",
elm->name, td->name, rv.code);
return rv;
}
asn_enc_rval_t
CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
asn_TYPE_member_t *elm; /* CHOICE's element */
asn_per_constraint_t *ct;
void *memb_ptr;
int present;
int present_enc;
if(!sptr) ASN__ENCODE_FAILED;
ASN_DEBUG("Encoding %s as CHOICE", td->name);
if(constraints) ct = &constraints->value;
else if(td->per_constraints) ct = &td->per_constraints->value;
else ct = 0;
present = _fetch_present_idx(sptr,
specs->pres_offset, specs->pres_size);
/*
* If the structure was not initialized properly, it cannot be encoded:
* can't deduce what to encode in the choice type.
*/
if(present <= 0 || present > td->elements_count)
ASN__ENCODE_FAILED;
else
present--;
ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
/* Adjust if canonical order is different from natural order */
if(specs->canonical_order)
present_enc = specs->canonical_order[present];
else
present_enc = present;
if(ct && ct->range_bits >= 0) {
if(present_enc < ct->lower_bound
|| present_enc > ct->upper_bound) {
if(ct->flags & APC_EXTENSIBLE) {
if(per_put_few_bits(po, 1, 1))
ASN__ENCODE_FAILED;
} else {
ASN__ENCODE_FAILED;
}
ct = 0;
}
}
if(ct && ct->flags & APC_EXTENSIBLE)
if(per_put_few_bits(po, 0, 1))
ASN__ENCODE_FAILED;
elm = &td->elements[present];
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
if(!memb_ptr) ASN__ENCODE_FAILED;
} else {
memb_ptr = (char *)sptr + elm->memb_offset;
}
if(ct && ct->range_bits >= 0) {
if(per_put_few_bits(po, present_enc, ct->range_bits))
ASN__ENCODE_FAILED;
return elm->type->uper_encoder(elm->type, elm->per_constraints,
memb_ptr, po);
} else {
asn_enc_rval_t rval;
if(specs->ext_start == -1)
ASN__ENCODE_FAILED;
if(uper_put_nsnnwn(po, present_enc - specs->ext_start))
ASN__ENCODE_FAILED;
if(uper_open_type_put(elm->type, elm->per_constraints,
memb_ptr, po))
ASN__ENCODE_FAILED;
rval.encoded = 0;
ASN__ENCODED_OK(rval);
}
}
int
CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
int present;
if(!sptr) return (cb("", 8, app_key) < 0) ? -1 : 0;
/*
* Figure out which CHOICE element is encoded.
*/
present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
/*
* Print that element.
*/
if(present > 0 && present <= td->elements_count) {
asn_TYPE_member_t *elm = &td->elements[present-1];
const void *memb_ptr;
if(elm->flags & ATF_POINTER) {
memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
if(!memb_ptr) return (cb("", 8, app_key) < 0) ? -1 : 0;
} else {
memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
}
/* Print member's name and stuff */
if(0) {
if(cb(elm->name, strlen(elm->name), app_key) < 0
|| cb(": ", 2, app_key) < 0)
return -1;
}
return elm->type->print_struct(elm->type, memb_ptr, ilevel,
cb, app_key);
} else {
return (cb("", 8, app_key) < 0) ? -1 : 0;
}
}
void
CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
int present;
if(!td || !ptr)
return;
ASN_DEBUG("Freeing %s as CHOICE", td->name);
/*
* Figure out which CHOICE element is encoded.
*/
present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
/*
* Free that element.
*/
if(present > 0 && present <= td->elements_count) {
asn_TYPE_member_t *elm = &td->elements[present-1];
void *memb_ptr;
if(elm->flags & ATF_POINTER) {
memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
if(memb_ptr)
ASN_STRUCT_FREE(*elm->type, memb_ptr);
} else {
memb_ptr = (void *)((char *)ptr + elm->memb_offset);
ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);
}
}
if(!contents_only) {
FREEMEM(ptr);
}
}
/*
* The following functions functions offer protection against -fshort-enums,
* compatible with little- and big-endian machines.
* If assertion is triggered, either disable -fshort-enums, or add an entry
* here with the ->pres_size of your target stracture.
* Unless the target structure is packed, the ".present" member
* is guaranteed to be aligned properly. ASN.1 compiler itself does not
* produce packed code.
*/
static int
_fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) {
const void *present_ptr;
int present;
present_ptr = ((const char *)struct_ptr) + pres_offset;
switch(pres_size) {
case sizeof(int): present = *(const int *)present_ptr; break;
case sizeof(short): present = *(const short *)present_ptr; break;
case sizeof(char): present = *(const char *)present_ptr; break;
default:
/* ANSI C mandates enum to be equivalent to integer */
assert(pres_size != sizeof(int));
return 0; /* If not aborted, pass back safe value */
}
return present;
}
static void
_set_present_idx(void *struct_ptr, int pres_offset, int pres_size, int present) {
void *present_ptr;
present_ptr = ((char *)struct_ptr) + pres_offset;
switch(pres_size) {
case sizeof(int): *(int *)present_ptr = present; break;
case sizeof(short): *(short *)present_ptr = present; break;
case sizeof(char): *(char *)present_ptr = present; break;
default:
/* ANSI C mandates enum to be equivalent to integer */
assert(pres_size != sizeof(int));
}
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/constr_CHOICE.h 0000664 0000000 0000000 00000002602 15245442746 0027022 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004, 2005 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _CONSTR_CHOICE_H_
#define _CONSTR_CHOICE_H_
#include
#ifdef __cplusplus
extern "C" {
#endif
typedef const struct asn_CHOICE_specifics_s {
/*
* Target structure description.
*/
int struct_size; /* Size of the target structure. */
int ctx_offset; /* Offset of the asn_codec_ctx_t member */
int pres_offset; /* Identifier of the present member */
int pres_size; /* Size of the identifier (enum) */
/*
* Tags to members mapping table.
*/
const asn_TYPE_tag2member_t *tag2el;
int tag2el_count;
/* Canonical ordering of CHOICE elements, for PER */
int *canonical_order;
/*
* Extensions-related stuff.
*/
int ext_start; /* First member of extensions, or -1 */
} asn_CHOICE_specifics_t;
/*
* A set specialized functions dealing with the CHOICE type.
*/
asn_struct_free_f CHOICE_free;
asn_struct_print_f CHOICE_print;
asn_constr_check_f CHOICE_constraint;
ber_type_decoder_f CHOICE_decode_ber;
der_type_encoder_f CHOICE_encode_der;
xer_type_decoder_f CHOICE_decode_xer;
xer_type_encoder_f CHOICE_encode_xer;
per_type_decoder_f CHOICE_decode_uper;
per_type_encoder_f CHOICE_encode_uper;
asn_outmost_tag_f CHOICE_outmost_tag;
#ifdef __cplusplus
}
#endif
#endif /* _CONSTR_CHOICE_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/constr_SEQUENCE.c 0000664 0000000 0000000 00000107372 15245442746 0027305 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include
/*
* Number of bytes left for this structure.
* (ctx->left) indicates the number of bytes _transferred_ for the structure.
* (size) contains the number of bytes in the buffer passed.
*/
#define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left)
/*
* If the subprocessor function returns with an indication that it wants
* more data, it may well be a fatal decoding problem, because the
* size is constrained by the 's L, even if the buffer size allows
* reading more data.
* For example, consider the buffer containing the following TLVs:
* ...
* The TLV length clearly indicates that one byte is expected in V, but
* if the V processor returns with "want more data" even if the buffer
* contains way more data than the V processor have seen.
*/
#define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size)
/*
* This macro "eats" the part of the buffer which is definitely "consumed",
* i.e. was correctly converted into local representation or rightfully skipped.
*/
#undef ADVANCE
#define ADVANCE(num_bytes) do { \
size_t num = num_bytes; \
ptr = ((const char *)ptr) + num; \
size -= num; \
if(ctx->left >= 0) \
ctx->left -= num; \
consumed_myself += num; \
} while(0)
/*
* Switch to the next phase of parsing.
*/
#undef NEXT_PHASE
#undef PHASE_OUT
#define NEXT_PHASE(ctx) do { \
ctx->phase++; \
ctx->step = 0; \
} while(0)
#define PHASE_OUT(ctx) do { ctx->phase = 10; } while(0)
/*
* Return a standardized complex structure.
*/
#undef RETURN
#define RETURN(_code) do { \
rval.code = _code; \
rval.consumed = consumed_myself;\
return rval; \
} while(0)
/*
* Check whether we are inside the extensions group.
*/
#define IN_EXTENSION_GROUP(specs, memb_idx) \
( ((memb_idx) > (specs)->ext_after) \
&&((memb_idx) < (specs)->ext_before))
/*
* Tags are canonically sorted in the tag2element map.
*/
static int
_t2e_cmp(const void *ap, const void *bp) {
const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
int a_class = BER_TAG_CLASS(a->el_tag);
int b_class = BER_TAG_CLASS(b->el_tag);
if(a_class == b_class) {
ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
if(a_value == b_value) {
if(a->el_no > b->el_no)
return 1;
/*
* Important: we do not check
* for a->el_no <= b->el_no!
*/
return 0;
} else if(a_value < b_value)
return -1;
else
return 1;
} else if(a_class < b_class) {
return -1;
} else {
return 1;
}
}
/*
* The decoder of the SEQUENCE type.
*/
asn_dec_rval_t
SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
/*
* Bring closer parts of structure description.
*/
asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
asn_TYPE_member_t *elements = td->elements;
/*
* Parts of the structure being constructed.
*/
void *st = *struct_ptr; /* Target structure. */
asn_struct_ctx_t *ctx; /* Decoder context */
ber_tlv_tag_t tlv_tag; /* T from TLV */
asn_dec_rval_t rval; /* Return code from subparsers */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
int edx; /* SEQUENCE element's index */
ASN_DEBUG("Decoding %s as SEQUENCE", td->name);
/*
* Create the target structure if it is not present already.
*/
if(st == 0) {
st = *struct_ptr = CALLOC(1, specs->struct_size);
if(st == 0) {
RETURN(RC_FAIL);
}
}
/*
* Restore parsing context.
*/
ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
/*
* Start to parse where left previously
*/
switch(ctx->phase) {
case 0:
/*
* PHASE 0.
* Check that the set of tags associated with given structure
* perfectly fits our expectations.
*/
rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
tag_mode, 1, &ctx->left, 0);
if(rval.code != RC_OK) {
ASN_DEBUG("%s tagging check failed: %d",
td->name, rval.code);
return rval;
}
if(ctx->left >= 0)
ctx->left += rval.consumed; /* ?Substracted below! */
ADVANCE(rval.consumed);
NEXT_PHASE(ctx);
ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
(long)ctx->left, (long)size);
/* Fall through */
case 1:
/*
* PHASE 1.
* From the place where we've left it previously,
* try to decode the next member from the list of
* this structure's elements.
* (ctx->step) stores the member being processed
* between invocations and the microphase {0,1} of parsing
* that member:
* step = ( * 2 + ).
*/
for(edx = (ctx->step >> 1); edx < td->elements_count;
edx++, ctx->step = (ctx->step & ~1) + 2) {
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
ssize_t tag_len; /* Length of TLV's T */
int opt_edx_end; /* Next non-optional element */
int use_bsearch;
int n;
if(ctx->step & 1)
goto microphase2;
/*
* MICROPHASE 1: Synchronize decoding.
*/
ASN_DEBUG("In %s SEQUENCE left %d, edx=%d flags=%d"
" opt=%d ec=%d",
td->name, (int)ctx->left, edx,
elements[edx].flags, elements[edx].optional,
td->elements_count);
if(ctx->left == 0 /* No more stuff is expected */
&& (
/* Explicit OPTIONAL specification reaches the end */
(edx + elements[edx].optional
== td->elements_count)
||
/* All extensions are optional */
(IN_EXTENSION_GROUP(specs, edx)
&& specs->ext_before > td->elements_count)
)
) {
ASN_DEBUG("End of SEQUENCE %s", td->name);
/*
* Found the legitimate end of the structure.
*/
PHASE_OUT(ctx);
RETURN(RC_OK);
}
/*
* Fetch the T from TLV.
*/
tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
ASN_DEBUG("Current tag in %s SEQUENCE for element %d "
"(%s) is %s encoded in %d bytes, of frame %ld",
td->name, edx, elements[edx].name,
ber_tlv_tag_string(tlv_tag), (int)tag_len, (long)LEFT);
switch(tag_len) {
case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
/* Fall through */
case -1: RETURN(RC_FAIL);
}
if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
if(LEFT < 2) {
if(SIZE_VIOLATION)
RETURN(RC_FAIL);
else
RETURN(RC_WMORE);
} else if(((const uint8_t *)ptr)[1] == 0) {
ASN_DEBUG("edx = %d, opt = %d, ec=%d",
edx, elements[edx].optional,
td->elements_count);
if((edx + elements[edx].optional
== td->elements_count)
|| (IN_EXTENSION_GROUP(specs, edx)
&& specs->ext_before
> td->elements_count)) {
/*
* Yeah, baby! Found the terminator
* of the indefinite length structure.
*/
/*
* Proceed to the canonical
* finalization function.
* No advancing is necessary.
*/
goto phase3;
}
}
}
/*
* Find the next available type with this tag.
*/
use_bsearch = 0;
opt_edx_end = edx + elements[edx].optional + 1;
if(opt_edx_end > td->elements_count)
opt_edx_end = td->elements_count; /* Cap */
else if(opt_edx_end - edx > 8) {
/* Limit the scope of linear search... */
opt_edx_end = edx + 8;
use_bsearch = 1;
/* ... and resort to bsearch() */
}
for(n = edx; n < opt_edx_end; n++) {
if(BER_TAGS_EQUAL(tlv_tag, elements[n].tag)) {
/*
* Found element corresponding to the tag
* being looked at.
* Reposition over the right element.
*/
edx = n;
ctx->step = 1 + 2 * edx; /* Remember! */
goto microphase2;
} else if(elements[n].flags & ATF_OPEN_TYPE) {
/*
* This is the ANY type, which may bear
* any flag whatsoever.
*/
edx = n;
ctx->step = 1 + 2 * edx; /* Remember! */
goto microphase2;
} else if(elements[n].tag == (ber_tlv_tag_t)-1) {
use_bsearch = 1;
break;
}
}
if(use_bsearch) {
/*
* Resort to a binary search over
* sorted array of tags.
*/
const asn_TYPE_tag2member_t *t2m;
asn_TYPE_tag2member_t key;
key.el_tag = tlv_tag;
key.el_no = edx;
t2m = (const asn_TYPE_tag2member_t *)bsearch(&key,
specs->tag2el, specs->tag2el_count,
sizeof(specs->tag2el[0]), _t2e_cmp);
if(t2m) {
const asn_TYPE_tag2member_t *best = 0;
const asn_TYPE_tag2member_t *t2m_f, *t2m_l;
int edx_max = edx + elements[edx].optional;
/*
* Rewind to the first element with that tag,
* `cause bsearch() does not guarantee order.
*/
t2m_f = t2m + t2m->toff_first;
t2m_l = t2m + t2m->toff_last;
for(t2m = t2m_f; t2m <= t2m_l; t2m++) {
if(t2m->el_no > edx_max) break;
if(t2m->el_no < edx) continue;
best = t2m;
}
if(best) {
edx = best->el_no;
ctx->step = 1 + 2 * edx;
goto microphase2;
}
}
n = opt_edx_end;
}
if(n == opt_edx_end) {
/*
* If tag is unknown, it may be either
* an unknown (thus, incorrect) tag,
* or an extension (...),
* or an end of the indefinite-length structure.
*/
if(!IN_EXTENSION_GROUP(specs,
edx + elements[edx].optional)) {
ASN_DEBUG("Unexpected tag %s (at %d)",
ber_tlv_tag_string(tlv_tag), edx);
ASN_DEBUG("Expected tag %s (%s)%s",
ber_tlv_tag_string(elements[edx].tag),
elements[edx].name,
elements[edx].optional
?" or alternatives":"");
RETURN(RC_FAIL);
} else {
/* Skip this tag */
ssize_t skip;
edx += elements[edx].optional;
ASN_DEBUG("Skipping unexpected %s (at %d)",
ber_tlv_tag_string(tlv_tag), edx);
skip = ber_skip_length(opt_codec_ctx,
BER_TLV_CONSTRUCTED(ptr),
(const char *)ptr + tag_len,
LEFT - tag_len);
ASN_DEBUG("Skip length %d in %s",
(int)skip, td->name);
switch(skip) {
case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
/* Fall through */
case -1: RETURN(RC_FAIL);
}
ADVANCE(skip + tag_len);
ctx->step -= 2;
edx--;
continue; /* Try again with the next tag */
}
}
/*
* MICROPHASE 2: Invoke the member-specific decoder.
*/
ctx->step |= 1; /* Confirm entering next microphase */
microphase2:
ASN_DEBUG("Inside SEQUENCE %s MF2", td->name);
/*
* Compute the position of the member inside a structure,
* and also a type of containment (it may be contained
* as pointer or using inline inclusion).
*/
if(elements[edx].flags & ATF_POINTER) {
/* Member is a pointer to another structure */
memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset);
} else {
/*
* A pointer to a pointer
* holding the start of the structure
*/
memb_ptr = (char *)st + elements[edx].memb_offset;
memb_ptr2 = &memb_ptr;
}
/*
* Invoke the member fetch routine according to member's type
*/
rval = elements[edx].type->ber_decoder(opt_codec_ctx,
elements[edx].type,
memb_ptr2, ptr, LEFT,
elements[edx].tag_mode);
ASN_DEBUG("In %s SEQUENCE decoded %d %s of %d "
"in %d bytes rval.code %d, size=%d",
td->name, edx, elements[edx].type->name,
(int)LEFT, (int)rval.consumed, rval.code, (int)size);
switch(rval.code) {
case RC_OK:
break;
case RC_WMORE: /* More data expected */
if(!SIZE_VIOLATION) {
ADVANCE(rval.consumed);
RETURN(RC_WMORE);
}
ASN_DEBUG("Size violation (c->l=%ld <= s=%ld)",
(long)ctx->left, (long)size);
/* Fall through */
case RC_FAIL: /* Fatal error */
RETURN(RC_FAIL);
} /* switch(rval) */
ADVANCE(rval.consumed);
} /* for(all structure members) */
phase3:
ctx->phase = 3;
case 3: /* 00 and other tags expected */
case 4: /* only 00's expected */
ASN_DEBUG("SEQUENCE %s Leftover: %ld, size = %ld",
td->name, (long)ctx->left, (long)size);
/*
* Skip everything until the end of the SEQUENCE.
*/
while(ctx->left) {
ssize_t tl, ll;
tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
switch(tl) {
case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
/* Fall through */
case -1: RETURN(RC_FAIL);
}
/*
* If expected <0><0>...
*/
if(ctx->left < 0
&& ((const uint8_t *)ptr)[0] == 0) {
if(LEFT < 2) {
if(SIZE_VIOLATION)
RETURN(RC_FAIL);
else
RETURN(RC_WMORE);
} else if(((const uint8_t *)ptr)[1] == 0) {
/*
* Correctly finished with <0><0>.
*/
ADVANCE(2);
ctx->left++;
ctx->phase = 4;
continue;
}
}
if(!IN_EXTENSION_GROUP(specs, td->elements_count)
|| ctx->phase == 4) {
ASN_DEBUG("Unexpected continuation "
"of a non-extensible type "
"%s (SEQUENCE): %s",
td->name,
ber_tlv_tag_string(tlv_tag));
RETURN(RC_FAIL);
}
ll = ber_skip_length(opt_codec_ctx,
BER_TLV_CONSTRUCTED(ptr),
(const char *)ptr + tl, LEFT - tl);
switch(ll) {
case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
/* Fall through */
case -1: RETURN(RC_FAIL);
}
ADVANCE(tl + ll);
}
PHASE_OUT(ctx);
}
RETURN(RC_OK);
}
/*
* The DER encoder of the SEQUENCE type.
*/
asn_enc_rval_t
SEQUENCE_encode_der(asn_TYPE_descriptor_t *td,
void *sptr, int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
size_t computed_size = 0;
asn_enc_rval_t erval;
ssize_t ret;
int edx;
ASN_DEBUG("%s %s as SEQUENCE",
cb?"Encoding":"Estimating", td->name);
/*
* Gather the length of the underlying members sequence.
*/
for(edx = 0; edx < td->elements_count; edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
void *memb_ptr;
if(elm->flags & ATF_POINTER) {
memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
if(!memb_ptr) {
if(elm->optional) continue;
/* Mandatory element is missing */
ASN__ENCODE_FAILED;
}
} else {
memb_ptr = (void *)((char *)sptr + elm->memb_offset);
}
erval = elm->type->der_encoder(elm->type, memb_ptr,
elm->tag_mode, elm->tag,
0, 0);
if(erval.encoded == -1)
return erval;
computed_size += erval.encoded;
ASN_DEBUG("Member %d %s estimated %ld bytes",
edx, elm->name, (long)erval.encoded);
}
/*
* Encode the TLV for the sequence itself.
*/
ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
ASN_DEBUG("Wrote tags: %ld (+%ld)", (long)ret, (long)computed_size);
if(ret == -1)
ASN__ENCODE_FAILED;
erval.encoded = computed_size + ret;
if(!cb) ASN__ENCODED_OK(erval);
/*
* Encode all members.
*/
for(edx = 0; edx < td->elements_count; edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
asn_enc_rval_t tmperval;
void *memb_ptr;
if(elm->flags & ATF_POINTER) {
memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
if(!memb_ptr) continue;
} else {
memb_ptr = (void *)((char *)sptr + elm->memb_offset);
}
tmperval = elm->type->der_encoder(elm->type, memb_ptr,
elm->tag_mode, elm->tag,
cb, app_key);
if(tmperval.encoded == -1)
return tmperval;
computed_size -= tmperval.encoded;
ASN_DEBUG("Member %d %s of SEQUENCE %s encoded in %ld bytes",
edx, elm->name, td->name, (long)tmperval.encoded);
}
if(computed_size != 0)
/*
* Encoded size is not equal to the computed size.
*/
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(erval);
}
#undef XER_ADVANCE
#define XER_ADVANCE(num_bytes) do { \
size_t num = num_bytes; \
buf_ptr = ((const char *)buf_ptr) + num;\
size -= num; \
consumed_myself += num; \
} while(0)
/*
* Decode the XER (XML) data.
*/
asn_dec_rval_t
SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **struct_ptr, const char *opt_mname,
const void *buf_ptr, size_t size) {
/*
* Bring closer parts of structure description.
*/
asn_SEQUENCE_specifics_t *specs
= (asn_SEQUENCE_specifics_t *)td->specifics;
asn_TYPE_member_t *elements = td->elements;
const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
/*
* ... and parts of the structure being constructed.
*/
void *st = *struct_ptr; /* Target structure. */
asn_struct_ctx_t *ctx; /* Decoder context */
asn_dec_rval_t rval; /* Return value from a decoder */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
int edx; /* Element index */
int edx_end;
/*
* Create the target structure if it is not present already.
*/
if(st == 0) {
st = *struct_ptr = CALLOC(1, specs->struct_size);
if(st == 0) RETURN(RC_FAIL);
}
/*
* Restore parsing context.
*/
ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
/*
* Phases of XER/XML processing:
* Phase 0: Check that the opening tag matches our expectations.
* Phase 1: Processing body and reacting on closing tag.
* Phase 2: Processing inner type.
* Phase 3: Skipping unknown extensions.
* Phase 4: PHASED OUT
*/
for(edx = ctx->step; ctx->phase <= 3;) {
pxer_chunk_type_e ch_type; /* XER chunk type */
ssize_t ch_size; /* Chunk size */
xer_check_tag_e tcv; /* Tag check value */
asn_TYPE_member_t *elm;
int n;
/*
* Go inside the inner member of a sequence.
*/
if(ctx->phase == 2) {
asn_dec_rval_t tmprval;
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
elm = &td->elements[edx];
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
memb_ptr2 = (void **)((char *)st + elm->memb_offset);
} else {
memb_ptr = (char *)st + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
/* Invoke the inner type decoder, m.b. multiple times */
tmprval = elm->type->xer_decoder(opt_codec_ctx,
elm->type, memb_ptr2, elm->name,
buf_ptr, size);
XER_ADVANCE(tmprval.consumed);
if(tmprval.code != RC_OK)
RETURN(tmprval.code);
ctx->phase = 1; /* Back to body processing */
ctx->step = ++edx;
ASN_DEBUG("XER/SEQUENCE phase => %d, step => %d",
ctx->phase, ctx->step);
/* Fall through */
}
/*
* Get the next part of the XML stream.
*/
ch_size = xer_next_token(&ctx->context, buf_ptr, size,
&ch_type);
if(ch_size == -1) {
RETURN(RC_FAIL);
} else {
switch(ch_type) {
case PXER_WMORE:
RETURN(RC_WMORE);
case PXER_COMMENT: /* Got XML comment */
case PXER_TEXT: /* Ignore free-standing text */
XER_ADVANCE(ch_size); /* Skip silently */
continue;
case PXER_TAG:
break; /* Check the rest down there */
}
}
tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d [%s]",
tcv, ctx->phase, xml_tag);
/* Skip the extensions section */
if(ctx->phase == 3) {
switch(xer_skip_unknown(tcv, &ctx->left)) {
case -1:
ctx->phase = 4;
RETURN(RC_FAIL);
case 0:
XER_ADVANCE(ch_size);
continue;
case 1:
XER_ADVANCE(ch_size);
ctx->phase = 1;
continue;
case 2:
ctx->phase = 1;
break;
}
}
switch(tcv) {
case XCT_CLOSING:
if(ctx->phase == 0) break;
ctx->phase = 0;
/* Fall through */
case XCT_BOTH:
if(ctx->phase == 0) {
if(edx >= td->elements_count
||
/* Explicit OPTIONAL specs reaches the end */
(edx + elements[edx].optional
== td->elements_count)
||
/* All extensions are optional */
(IN_EXTENSION_GROUP(specs, edx)
&& specs->ext_before
> td->elements_count)
) {
XER_ADVANCE(ch_size);
ctx->phase = 4; /* Phase out */
RETURN(RC_OK);
} else {
ASN_DEBUG("Premature end of XER SEQUENCE");
RETURN(RC_FAIL);
}
}
/* Fall through */
case XCT_OPENING:
if(ctx->phase == 0) {
XER_ADVANCE(ch_size);
ctx->phase = 1; /* Processing body phase */
continue;
}
/* Fall through */
case XCT_UNKNOWN_OP:
case XCT_UNKNOWN_BO:
ASN_DEBUG("XER/SEQUENCE: tcv=%d, ph=%d, edx=%d",
tcv, ctx->phase, edx);
if(ctx->phase != 1) {
break; /* Really unexpected */
}
if(edx < td->elements_count) {
/*
* Search which member corresponds to this tag.
*/
edx_end = edx + elements[edx].optional + 1;
if(edx_end > td->elements_count)
edx_end = td->elements_count;
for(n = edx; n < edx_end; n++) {
elm = &td->elements[n];
tcv = xer_check_tag(buf_ptr,
ch_size, elm->name);
switch(tcv) {
case XCT_BOTH:
case XCT_OPENING:
/*
* Process this member.
*/
ctx->step = edx = n;
ctx->phase = 2;
break;
case XCT_UNKNOWN_OP:
case XCT_UNKNOWN_BO:
continue;
default:
n = edx_end;
break; /* Phase out */
}
break;
}
if(n != edx_end)
continue;
} else {
ASN_DEBUG("Out of defined members: %d/%d",
edx, td->elements_count);
}
/* It is expected extension */
if(IN_EXTENSION_GROUP(specs,
edx + (edx < td->elements_count
? elements[edx].optional : 0))) {
ASN_DEBUG("Got anticipated extension at %d",
edx);
/*
* Check for (XCT_BOTH or XCT_UNKNOWN_BO)
* By using a mask. Only record a pure
* tags.
*/
if(tcv & XCT_CLOSING) {
/* Found without body */
} else {
ctx->left = 1;
ctx->phase = 3; /* Skip ...'s */
}
XER_ADVANCE(ch_size);
continue;
}
/* Fall through */
default:
break;
}
ASN_DEBUG("Unexpected XML tag in SEQUENCE [%c%c%c%c%c%c]",
size>0?((const char *)buf_ptr)[0]:'.',
size>1?((const char *)buf_ptr)[1]:'.',
size>2?((const char *)buf_ptr)[2]:'.',
size>3?((const char *)buf_ptr)[3]:'.',
size>4?((const char *)buf_ptr)[4]:'.',
size>5?((const char *)buf_ptr)[5]:'.');
break;
}
ctx->phase = 4; /* "Phase out" on hard failure */
RETURN(RC_FAIL);
}
asn_enc_rval_t
SEQUENCE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_enc_rval_t er;
int xcan = (flags & XER_F_CANONICAL);
int edx;
if(!sptr)
ASN__ENCODE_FAILED;
er.encoded = 0;
for(edx = 0; edx < td->elements_count; edx++) {
asn_enc_rval_t tmper;
asn_TYPE_member_t *elm = &td->elements[edx];
void *memb_ptr;
const char *mname = elm->name;
unsigned int mlen = strlen(mname);
if(elm->flags & ATF_POINTER) {
memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
if(!memb_ptr) {
if(elm->optional)
continue;
/* Mandatory element is missing */
ASN__ENCODE_FAILED;
}
} else {
memb_ptr = (void *)((char *)sptr + elm->memb_offset);
}
if(!xcan) ASN__TEXT_INDENT(1, ilevel);
ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
/* Print the member itself */
tmper = elm->type->xer_encoder(elm->type, memb_ptr,
ilevel + 1, flags, cb, app_key);
if(tmper.encoded == -1) return tmper;
ASN__CALLBACK3("", 2, mname, mlen, ">", 1);
er.encoded += 5 + (2 * mlen) + tmper.encoded;
}
if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
ASN__ENCODED_OK(er);
cb_failed:
ASN__ENCODE_FAILED;
}
int
SEQUENCE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
int edx;
int ret;
if(!sptr) return (cb("", 8, app_key) < 0) ? -1 : 0;
/* Dump preamble */
if(cb(td->name, strlen(td->name), app_key) < 0
|| cb(" ::= {", 6, app_key) < 0)
return -1;
for(edx = 0; edx < td->elements_count; edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
const void *memb_ptr;
if(elm->flags & ATF_POINTER) {
memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
if(!memb_ptr) {
if(elm->optional) continue;
/* Print line */
/* Fall through */
}
} else {
memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
}
/* Indentation */
_i_INDENT(1);
/* Print the member's name and stuff */
if(cb(elm->name, strlen(elm->name), app_key) < 0
|| cb(": ", 2, app_key) < 0)
return -1;
/* Print the member itself */
ret = elm->type->print_struct(elm->type, memb_ptr, ilevel + 1,
cb, app_key);
if(ret) return ret;
}
ilevel--;
_i_INDENT(1);
return (cb("}", 1, app_key) < 0) ? -1 : 0;
}
void
SEQUENCE_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
int edx;
if(!td || !sptr)
return;
ASN_DEBUG("Freeing %s as SEQUENCE", td->name);
for(edx = 0; edx < td->elements_count; edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
void *memb_ptr;
if(elm->flags & ATF_POINTER) {
memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
if(memb_ptr)
ASN_STRUCT_FREE(*elm->type, memb_ptr);
} else {
memb_ptr = (void *)((char *)sptr + elm->memb_offset);
ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);
}
}
if(!contents_only) {
FREEMEM(sptr);
}
}
int
SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
int edx;
if(!sptr) {
ASN__CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
/*
* Iterate over structure members and check their validity.
*/
for(edx = 0; edx < td->elements_count; edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
const void *memb_ptr;
if(elm->flags & ATF_POINTER) {
memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
if(!memb_ptr) {
if(elm->optional)
continue;
ASN__CTFAIL(app_key, td, sptr,
"%s: mandatory element %s absent (%s:%d)",
td->name, elm->name, __FILE__, __LINE__);
return -1;
}
} else {
memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
}
if(elm->memb_constraints) {
int ret = elm->memb_constraints(elm->type, memb_ptr,
ctfailcb, app_key);
if(ret) return ret;
} else {
int ret = elm->type->check_constraints(elm->type,
memb_ptr, ctfailcb, app_key);
if(ret) return ret;
/*
* Cannot inherit it earlier:
* need to make sure we get the updated version.
*/
elm->memb_constraints = elm->type->check_constraints;
}
}
return 0;
}
asn_dec_rval_t
SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
void *st = *sptr; /* Target structure. */
int extpresent; /* Extension additions are present */
uint8_t *opres; /* Presence of optional root members */
asn_per_data_t opmd;
asn_dec_rval_t rv;
int edx;
(void)constraints;
if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
ASN__DECODE_FAILED;
if(!st) {
st = *sptr = CALLOC(1, specs->struct_size);
if(!st) ASN__DECODE_FAILED;
}
ASN_DEBUG("Decoding %s as SEQUENCE (UPER)", td->name);
/* Handle extensions */
if(specs->ext_before >= 0) {
extpresent = per_get_few_bits(pd, 1);
if(extpresent < 0) ASN__DECODE_STARVED;
} else {
extpresent = 0;
}
/* Prepare a place and read-in the presence bitmap */
memset(&opmd, 0, sizeof(opmd));
if(specs->roms_count) {
opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1);
if(!opres) ASN__DECODE_FAILED;
/* Get the presence map */
if(per_get_many_bits(pd, opres, 0, specs->roms_count)) {
FREEMEM(opres);
ASN__DECODE_STARVED;
}
opmd.buffer = opres;
opmd.nbits = specs->roms_count;
ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)",
td->name, specs->roms_count, *opres);
} else {
opres = 0;
}
/*
* Get the sequence ROOT elements.
*/
for(edx = 0; edx < td->elements_count; edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
if(IN_EXTENSION_GROUP(specs, edx))
continue;
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)st + elm->memb_offset);
} else {
memb_ptr = (char *)st + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
/* Deal with optionality */
if(elm->optional) {
int present = per_get_few_bits(&opmd, 1);
ASN_DEBUG("Member %s->%s is optional, p=%d (%d->%d)",
td->name, elm->name, present,
(int)opmd.nboff, (int)opmd.nbits);
if(present == 0) {
/* This element is not present */
if(elm->default_value) {
/* Fill-in DEFAULT */
if(elm->default_value(1, memb_ptr2)) {
FREEMEM(opres);
ASN__DECODE_FAILED;
}
ASN_DEBUG("Filled-in default");
}
/* The member is just not present */
continue;
}
/* Fall through */
}
/* Fetch the member from the stream */
ASN_DEBUG("Decoding member %s in %s", elm->name, td->name);
rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
elm->per_constraints, memb_ptr2, pd);
if(rv.code != RC_OK) {
ASN_DEBUG("Failed decode %s in %s",
elm->name, td->name);
FREEMEM(opres);
return rv;
}
}
/* Optionality map is not needed anymore */
FREEMEM(opres);
/*
* Deal with extensions.
*/
if(extpresent) {
ssize_t bmlength;
uint8_t *epres; /* Presence of extension members */
asn_per_data_t epmd;
bmlength = uper_get_nslength(pd);
if(bmlength < 0) ASN__DECODE_STARVED;
ASN_DEBUG("Extensions %ld present in %s", (long)bmlength, td->name);
epres = (uint8_t *)MALLOC((bmlength + 15) >> 3);
if(!epres) ASN__DECODE_STARVED;
/* Get the extensions map */
if(per_get_many_bits(pd, epres, 0, bmlength)) {
FREEMEM(epres);
ASN__DECODE_STARVED;
}
memset(&epmd, 0, sizeof(epmd));
epmd.buffer = epres;
epmd.nbits = bmlength;
ASN_DEBUG("Read in extensions bitmap for %s of %ld bits (%x..)",
td->name, (long)bmlength, *epres);
/* Go over extensions and read them in */
for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
int present;
if(!IN_EXTENSION_GROUP(specs, edx)) {
ASN_DEBUG("%d is not extension", edx);
continue;
}
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)st + elm->memb_offset);
} else {
memb_ptr = (void *)((char *)st + elm->memb_offset);
memb_ptr2 = &memb_ptr;
}
present = per_get_few_bits(&epmd, 1);
if(present <= 0) {
if(present < 0) break; /* No more extensions */
continue;
}
ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name, *memb_ptr2);
rv = uper_open_type_get(opt_codec_ctx, elm->type,
elm->per_constraints, memb_ptr2, pd);
if(rv.code != RC_OK) {
FREEMEM(epres);
return rv;
}
}
/* Skip over overflow extensions which aren't present
* in this system's version of the protocol */
for(;;) {
ASN_DEBUG("Getting overflow extensions");
switch(per_get_few_bits(&epmd, 1)) {
case -1: break;
case 0: continue;
default:
if(uper_open_type_skip(opt_codec_ctx, pd)) {
FREEMEM(epres);
ASN__DECODE_STARVED;
}
}
break;
}
FREEMEM(epres);
}
/* Fill DEFAULT members in extensions */
for(edx = specs->roms_count; edx < specs->roms_count
+ specs->aoms_count; edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
void **memb_ptr2; /* Pointer to member pointer */
if(!elm->default_value) continue;
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)st
+ elm->memb_offset);
if(*memb_ptr2) continue;
} else {
continue; /* Extensions are all optionals */
}
/* Set default value */
if(elm->default_value(1, memb_ptr2)) {
ASN__DECODE_FAILED;
}
}
rv.consumed = 0;
rv.code = RC_OK;
return rv;
}
static int
SEQUENCE_handle_extensions(asn_TYPE_descriptor_t *td, void *sptr,
asn_per_outp_t *po1, asn_per_outp_t *po2) {
asn_SEQUENCE_specifics_t *specs
= (asn_SEQUENCE_specifics_t *)td->specifics;
int exts_present = 0;
int exts_count = 0;
int edx;
if(specs->ext_before < 0)
return 0;
/* Find out which extensions are present */
for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
int present;
if(!IN_EXTENSION_GROUP(specs, edx)) {
ASN_DEBUG("%s (@%d) is not extension", elm->type->name, edx);
continue;
}
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
present = (*memb_ptr2 != 0);
} else {
memb_ptr = (void *)((char *)sptr + elm->memb_offset);
memb_ptr2 = &memb_ptr;
present = 1;
}
ASN_DEBUG("checking %s (@%d) present => %d",
elm->type->name, edx, present);
exts_count++;
exts_present += present;
/* Encode as presence marker */
if(po1 && per_put_few_bits(po1, present, 1))
return -1;
/* Encode as open type field */
if(po2 && present && uper_open_type_put(elm->type,
elm->per_constraints, *memb_ptr2, po2))
return -1;
}
return exts_present ? exts_count : 0;
}
asn_enc_rval_t
SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_SEQUENCE_specifics_t *specs
= (asn_SEQUENCE_specifics_t *)td->specifics;
asn_enc_rval_t er;
int n_extensions;
int edx;
int i;
(void)constraints;
if(!sptr)
ASN__ENCODE_FAILED;
er.encoded = 0;
ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name);
/*
* X.691#18.1 Whether structure is extensible
* and whether to encode extensions
*/
if(specs->ext_before >= 0) {
n_extensions = SEQUENCE_handle_extensions(td, sptr, 0, 0);
per_put_few_bits(po, n_extensions ? 1 : 0, 1);
} else {
n_extensions = 0; /* There are no extensions to encode */
}
/* Encode a presence bitmap */
for(i = 0; i < specs->roms_count; i++) {
asn_TYPE_member_t *elm;
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
int present;
edx = specs->oms[i];
elm = &td->elements[edx];
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
present = (*memb_ptr2 != 0);
} else {
memb_ptr = (void *)((char *)sptr + elm->memb_offset);
memb_ptr2 = &memb_ptr;
present = 1;
}
/* Eliminate default values */
if(present && elm->default_value
&& elm->default_value(0, memb_ptr2) == 1)
present = 0;
ASN_DEBUG("Element %s %s %s->%s is %s",
elm->flags & ATF_POINTER ? "ptr" : "inline",
elm->default_value ? "def" : "wtv",
td->name, elm->name, present ? "present" : "absent");
if(per_put_few_bits(po, present, 1))
ASN__ENCODE_FAILED;
}
/*
* Encode the sequence ROOT elements.
*/
ASN_DEBUG("ext_after = %d, ec = %d, eb = %d", specs->ext_after, td->elements_count, specs->ext_before);
for(edx = 0; edx < ((specs->ext_after < 0)
? td->elements_count : specs->ext_before - 1); edx++) {
asn_TYPE_member_t *elm = &td->elements[edx];
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
if(IN_EXTENSION_GROUP(specs, edx))
continue;
ASN_DEBUG("About to encode %s", elm->type->name);
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
if(!*memb_ptr2) {
ASN_DEBUG("Element %s %d not present",
elm->name, edx);
if(elm->optional)
continue;
/* Mandatory element is missing */
ASN__ENCODE_FAILED;
}
} else {
memb_ptr = (void *)((char *)sptr + elm->memb_offset);
memb_ptr2 = &memb_ptr;
}
/* Eliminate default values */
if(elm->default_value && elm->default_value(0, memb_ptr2) == 1)
continue;
ASN_DEBUG("Encoding %s->%s", td->name, elm->name);
er = elm->type->uper_encoder(elm->type, elm->per_constraints,
*memb_ptr2, po);
if(er.encoded == -1)
return er;
}
/* No extensions to encode */
if(!n_extensions) ASN__ENCODED_OK(er);
ASN_DEBUG("Length of %d bit-map", n_extensions);
/* #18.8. Write down the presence bit-map length. */
if(uper_put_nslength(po, n_extensions))
ASN__ENCODE_FAILED;
ASN_DEBUG("Bit-map of %d elements", n_extensions);
/* #18.7. Encoding the extensions presence bit-map. */
/* TODO: act upon NOTE in #18.7 for canonical PER */
if(SEQUENCE_handle_extensions(td, sptr, po, 0) != n_extensions)
ASN__ENCODE_FAILED;
ASN_DEBUG("Writing %d extensions", n_extensions);
/* #18.9. Encode extensions as open type fields. */
if(SEQUENCE_handle_extensions(td, sptr, 0, po) != n_extensions)
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/constr_SEQUENCE.h 0000664 0000000 0000000 00000003006 15245442746 0027277 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _CONSTR_SEQUENCE_H_
#define _CONSTR_SEQUENCE_H_
#include
#ifdef __cplusplus
extern "C" {
#endif
typedef const struct asn_SEQUENCE_specifics_s {
/*
* Target structure description.
*/
int struct_size; /* Size of the target structure. */
int ctx_offset; /* Offset of the asn_struct_ctx_t member */
/*
* Tags to members mapping table (sorted).
*/
const asn_TYPE_tag2member_t *tag2el;
int tag2el_count;
/*
* Optional members of the extensions root (roms) or additions (aoms).
* Meaningful for PER.
*/
const int *oms; /* Optional MemberS */
int roms_count; /* Root optional members count */
int aoms_count; /* Additions optional members count */
/*
* Description of an extensions group.
*/
int ext_after; /* Extensions start after this member */
int ext_before; /* Extensions stop before this member */
} asn_SEQUENCE_specifics_t;
/*
* A set specialized functions dealing with the SEQUENCE type.
*/
asn_struct_free_f SEQUENCE_free;
asn_struct_print_f SEQUENCE_print;
asn_constr_check_f SEQUENCE_constraint;
ber_type_decoder_f SEQUENCE_decode_ber;
der_type_encoder_f SEQUENCE_encode_der;
xer_type_decoder_f SEQUENCE_decode_xer;
xer_type_encoder_f SEQUENCE_encode_xer;
per_type_decoder_f SEQUENCE_decode_uper;
per_type_encoder_f SEQUENCE_encode_uper;
#ifdef __cplusplus
}
#endif
#endif /* _CONSTR_SEQUENCE_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/constr_SEQUENCE_OF.c 0000664 0000000 0000000 00000012377 15245442746 0027671 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004, 2006 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include
/*
* The DER encoder of the SEQUENCE OF type.
*/
asn_enc_rval_t
SEQUENCE_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_TYPE_member_t *elm = td->elements;
asn_anonymous_sequence_ *list = _A_SEQUENCE_FROM_VOID(ptr);
size_t computed_size = 0;
ssize_t encoding_size = 0;
asn_enc_rval_t erval;
int edx;
ASN_DEBUG("Estimating size of SEQUENCE OF %s", td->name);
/*
* Gather the length of the underlying members sequence.
*/
for(edx = 0; edx < list->count; edx++) {
void *memb_ptr = list->array[edx];
if(!memb_ptr) continue;
erval = elm->type->der_encoder(elm->type, memb_ptr,
0, elm->tag,
0, 0);
if(erval.encoded == -1)
return erval;
computed_size += erval.encoded;
}
/*
* Encode the TLV for the sequence itself.
*/
encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag,
cb, app_key);
if(encoding_size == -1) {
erval.encoded = -1;
erval.failed_type = td;
erval.structure_ptr = ptr;
return erval;
}
computed_size += encoding_size;
if(!cb) {
erval.encoded = computed_size;
ASN__ENCODED_OK(erval);
}
ASN_DEBUG("Encoding members of SEQUENCE OF %s", td->name);
/*
* Encode all members.
*/
for(edx = 0; edx < list->count; edx++) {
void *memb_ptr = list->array[edx];
if(!memb_ptr) continue;
erval = elm->type->der_encoder(elm->type, memb_ptr,
0, elm->tag,
cb, app_key);
if(erval.encoded == -1)
return erval;
encoding_size += erval.encoded;
}
if(computed_size != (size_t)encoding_size) {
/*
* Encoded size is not equal to the computed size.
*/
erval.encoded = -1;
erval.failed_type = td;
erval.structure_ptr = ptr;
} else {
erval.encoded = computed_size;
erval.structure_ptr = 0;
erval.failed_type = 0;
}
return erval;
}
asn_enc_rval_t
SEQUENCE_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_enc_rval_t er;
asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
asn_TYPE_member_t *elm = td->elements;
asn_anonymous_sequence_ *list = _A_SEQUENCE_FROM_VOID(sptr);
const char *mname = specs->as_XMLValueList
? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag);
unsigned int mlen = mname ? strlen(mname) : 0;
int xcan = (flags & XER_F_CANONICAL);
int i;
if(!sptr) ASN__ENCODE_FAILED;
er.encoded = 0;
for(i = 0; i < list->count; i++) {
asn_enc_rval_t tmper;
void *memb_ptr = list->array[i];
if(!memb_ptr) continue;
if(mname) {
if(!xcan) ASN__TEXT_INDENT(1, ilevel);
ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
}
tmper = elm->type->xer_encoder(elm->type, memb_ptr,
ilevel + 1, flags, cb, app_key);
if(tmper.encoded == -1) return tmper;
if(tmper.encoded == 0 && specs->as_XMLValueList) {
const char *name = elm->type->xml_tag;
size_t len = strlen(name);
if(!xcan) ASN__TEXT_INDENT(1, ilevel + 1);
ASN__CALLBACK3("<", 1, name, len, "/>", 2);
}
if(mname) {
ASN__CALLBACK3("", 2, mname, mlen, ">", 1);
er.encoded += 5;
}
er.encoded += (2 * mlen) + tmper.encoded;
}
if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
ASN__ENCODED_OK(er);
cb_failed:
ASN__ENCODE_FAILED;
}
asn_enc_rval_t
SEQUENCE_OF_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
asn_anonymous_sequence_ *list;
asn_per_constraint_t *ct;
asn_enc_rval_t er;
asn_TYPE_member_t *elm = td->elements;
int seq;
if(!sptr) ASN__ENCODE_FAILED;
list = _A_SEQUENCE_FROM_VOID(sptr);
er.encoded = 0;
ASN_DEBUG("Encoding %s as SEQUENCE OF (%d)", td->name, list->count);
if(constraints) ct = &constraints->size;
else if(td->per_constraints) ct = &td->per_constraints->size;
else ct = 0;
/* If extensible constraint, check if size is in root */
if(ct) {
int not_in_root = (list->count < ct->lower_bound
|| list->count > ct->upper_bound);
ASN_DEBUG("lb %ld ub %ld %s",
ct->lower_bound, ct->upper_bound,
ct->flags & APC_EXTENSIBLE ? "ext" : "fix");
if(ct->flags & APC_EXTENSIBLE) {
/* Declare whether size is in extension root */
if(per_put_few_bits(po, not_in_root, 1))
ASN__ENCODE_FAILED;
if(not_in_root) ct = 0;
} else if(not_in_root && ct->effective_bits >= 0)
ASN__ENCODE_FAILED;
}
if(ct && ct->effective_bits >= 0) {
/* X.691, #19.5: No length determinant */
if(per_put_few_bits(po, list->count - ct->lower_bound,
ct->effective_bits))
ASN__ENCODE_FAILED;
}
for(seq = -1; seq < list->count;) {
ssize_t mayEncode;
if(seq < 0) seq = 0;
if(ct && ct->effective_bits >= 0) {
mayEncode = list->count;
} else {
mayEncode = uper_put_length(po, list->count - seq);
if(mayEncode < 0) ASN__ENCODE_FAILED;
}
while(mayEncode--) {
void *memb_ptr = list->array[seq++];
if(!memb_ptr) ASN__ENCODE_FAILED;
er = elm->type->uper_encoder(elm->type,
elm->per_constraints, memb_ptr, po);
if(er.encoded == -1)
ASN__ENCODE_FAILED;
}
}
ASN__ENCODED_OK(er);
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/constr_SEQUENCE_OF.h 0000664 0000000 0000000 00000001642 15245442746 0027667 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2005 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _CONSTR_SEQUENCE_OF_H_
#define _CONSTR_SEQUENCE_OF_H_
#include
#include /* Implemented using SET OF */
#ifdef __cplusplus
extern "C" {
#endif
/*
* A set specialized functions dealing with the SEQUENCE OF type.
* Generally implemented using SET OF.
*/
#define SEQUENCE_OF_free SET_OF_free
#define SEQUENCE_OF_print SET_OF_print
#define SEQUENCE_OF_constraint SET_OF_constraint
#define SEQUENCE_OF_decode_ber SET_OF_decode_ber
#define SEQUENCE_OF_decode_xer SET_OF_decode_xer
#define SEQUENCE_OF_decode_uper SET_OF_decode_uper
der_type_encoder_f SEQUENCE_OF_encode_der;
xer_type_encoder_f SEQUENCE_OF_encode_xer;
per_type_encoder_f SEQUENCE_OF_encode_uper;
#ifdef __cplusplus
}
#endif
#endif /* _CONSTR_SET_OF_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/constr_SET_OF.c 0000664 0000000 0000000 00000056045 15245442746 0027114 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004, 2005 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include
/*
* Number of bytes left for this structure.
* (ctx->left) indicates the number of bytes _transferred_ for the structure.
* (size) contains the number of bytes in the buffer passed.
*/
#define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left)
/*
* If the subprocessor function returns with an indication that it wants
* more data, it may well be a fatal decoding problem, because the
* size is constrained by the 's L, even if the buffer size allows
* reading more data.
* For example, consider the buffer containing the following TLVs:
* ...
* The TLV length clearly indicates that one byte is expected in V, but
* if the V processor returns with "want more data" even if the buffer
* contains way more data than the V processor have seen.
*/
#define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size)
/*
* This macro "eats" the part of the buffer which is definitely "consumed",
* i.e. was correctly converted into local representation or rightfully skipped.
*/
#undef ADVANCE
#define ADVANCE(num_bytes) do { \
size_t num = num_bytes; \
ptr = ((const char *)ptr) + num;\
size -= num; \
if(ctx->left >= 0) \
ctx->left -= num; \
consumed_myself += num; \
} while(0)
/*
* Switch to the next phase of parsing.
*/
#undef NEXT_PHASE
#undef PHASE_OUT
#define NEXT_PHASE(ctx) do { \
ctx->phase++; \
ctx->step = 0; \
} while(0)
#define PHASE_OUT(ctx) do { ctx->phase = 10; } while(0)
/*
* Return a standardized complex structure.
*/
#undef RETURN
#define RETURN(_code) do { \
rval.code = _code; \
rval.consumed = consumed_myself;\
return rval; \
} while(0)
/*
* The decoder of the SET OF type.
*/
asn_dec_rval_t
SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
/*
* Bring closer parts of structure description.
*/
asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
asn_TYPE_member_t *elm = td->elements; /* Single one */
/*
* Parts of the structure being constructed.
*/
void *st = *struct_ptr; /* Target structure. */
asn_struct_ctx_t *ctx; /* Decoder context */
ber_tlv_tag_t tlv_tag; /* T from TLV */
asn_dec_rval_t rval; /* Return code from subparsers */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
ASN_DEBUG("Decoding %s as SET OF", td->name);
/*
* Create the target structure if it is not present already.
*/
if(st == 0) {
st = *struct_ptr = CALLOC(1, specs->struct_size);
if(st == 0) {
RETURN(RC_FAIL);
}
}
/*
* Restore parsing context.
*/
ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
/*
* Start to parse where left previously
*/
switch(ctx->phase) {
case 0:
/*
* PHASE 0.
* Check that the set of tags associated with given structure
* perfectly fits our expectations.
*/
rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
tag_mode, 1, &ctx->left, 0);
if(rval.code != RC_OK) {
ASN_DEBUG("%s tagging check failed: %d",
td->name, rval.code);
return rval;
}
if(ctx->left >= 0)
ctx->left += rval.consumed; /* ?Substracted below! */
ADVANCE(rval.consumed);
ASN_DEBUG("Structure consumes %ld bytes, "
"buffer %ld", (long)ctx->left, (long)size);
NEXT_PHASE(ctx);
/* Fall through */
case 1:
/*
* PHASE 1.
* From the place where we've left it previously,
* try to decode the next item.
*/
for(;; ctx->step = 0) {
ssize_t tag_len; /* Length of TLV's T */
if(ctx->step & 1)
goto microphase2;
/*
* MICROPHASE 1: Synchronize decoding.
*/
if(ctx->left == 0) {
ASN_DEBUG("End of SET OF %s", td->name);
/*
* No more things to decode.
* Exit out of here.
*/
PHASE_OUT(ctx);
RETURN(RC_OK);
}
/*
* Fetch the T from TLV.
*/
tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
switch(tag_len) {
case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
/* Fall through */
case -1: RETURN(RC_FAIL);
}
if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
if(LEFT < 2) {
if(SIZE_VIOLATION)
RETURN(RC_FAIL);
else
RETURN(RC_WMORE);
} else if(((const uint8_t *)ptr)[1] == 0) {
/*
* Found the terminator of the
* indefinite length structure.
*/
break;
}
}
/* Outmost tag may be unknown and cannot be fetched/compared */
if(elm->tag != (ber_tlv_tag_t)-1) {
if(BER_TAGS_EQUAL(tlv_tag, elm->tag)) {
/*
* The new list member of expected type has arrived.
*/
} else {
ASN_DEBUG("Unexpected tag %s fixed SET OF %s",
ber_tlv_tag_string(tlv_tag), td->name);
ASN_DEBUG("%s SET OF has tag %s",
td->name, ber_tlv_tag_string(elm->tag));
RETURN(RC_FAIL);
}
}
/*
* MICROPHASE 2: Invoke the member-specific decoder.
*/
ctx->step |= 1; /* Confirm entering next microphase */
microphase2:
/*
* Invoke the member fetch routine according to member's type
*/
rval = elm->type->ber_decoder(opt_codec_ctx,
elm->type, &ctx->ptr, ptr, LEFT, 0);
ASN_DEBUG("In %s SET OF %s code %d consumed %d",
td->name, elm->type->name,
rval.code, (int)rval.consumed);
switch(rval.code) {
case RC_OK:
{
asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
if(ASN_SET_ADD(list, ctx->ptr) != 0)
RETURN(RC_FAIL);
else
ctx->ptr = 0;
}
break;
case RC_WMORE: /* More data expected */
if(!SIZE_VIOLATION) {
ADVANCE(rval.consumed);
RETURN(RC_WMORE);
}
/* Fall through */
case RC_FAIL: /* Fatal error */
ASN_STRUCT_FREE(*elm->type, ctx->ptr);
ctx->ptr = 0;
RETURN(RC_FAIL);
} /* switch(rval) */
ADVANCE(rval.consumed);
} /* for(all list members) */
NEXT_PHASE(ctx);
case 2:
/*
* Read in all "end of content" TLVs.
*/
while(ctx->left < 0) {
if(LEFT < 2) {
if(LEFT > 0 && ((const char *)ptr)[0] != 0) {
/* Unexpected tag */
RETURN(RC_FAIL);
} else {
RETURN(RC_WMORE);
}
}
if(((const char *)ptr)[0] == 0
&& ((const char *)ptr)[1] == 0) {
ADVANCE(2);
ctx->left++;
} else {
RETURN(RC_FAIL);
}
}
PHASE_OUT(ctx);
}
RETURN(RC_OK);
}
/*
* Internally visible buffer holding a single encoded element.
*/
struct _el_buffer {
uint8_t *buf;
size_t length;
size_t size;
};
/* Append bytes to the above structure */
static int _el_addbytes(const void *buffer, size_t size, void *el_buf_ptr) {
struct _el_buffer *el_buf = (struct _el_buffer *)el_buf_ptr;
if(el_buf->length + size > el_buf->size)
return -1;
memcpy(el_buf->buf + el_buf->length, buffer, size);
el_buf->length += size;
return 0;
}
static int _el_buf_cmp(const void *ap, const void *bp) {
const struct _el_buffer *a = (const struct _el_buffer *)ap;
const struct _el_buffer *b = (const struct _el_buffer *)bp;
int ret;
size_t common_len;
if(a->length < b->length)
common_len = a->length;
else
common_len = b->length;
ret = memcmp(a->buf, b->buf, common_len);
if(ret == 0) {
if(a->length < b->length)
ret = -1;
else if(a->length > b->length)
ret = 1;
}
return ret;
}
/*
* The DER encoder of the SET OF type.
*/
asn_enc_rval_t
SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_TYPE_member_t *elm = td->elements;
asn_TYPE_descriptor_t *elm_type = elm->type;
der_type_encoder_f *der_encoder = elm_type->der_encoder;
asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr);
size_t computed_size = 0;
ssize_t encoding_size = 0;
struct _el_buffer *encoded_els;
ssize_t eels_count = 0;
size_t max_encoded_len = 1;
asn_enc_rval_t erval;
int ret;
int edx;
ASN_DEBUG("Estimating size for SET OF %s", td->name);
/*
* Gather the length of the underlying members sequence.
*/
for(edx = 0; edx < list->count; edx++) {
void *memb_ptr = list->array[edx];
if(!memb_ptr) continue;
erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, 0, 0);
if(erval.encoded == -1)
return erval;
computed_size += erval.encoded;
/* Compute maximum encoding's size */
if(max_encoded_len < (size_t)erval.encoded)
max_encoded_len = erval.encoded;
}
/*
* Encode the TLV for the sequence itself.
*/
encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag,
cb, app_key);
if(encoding_size == -1) {
erval.encoded = -1;
erval.failed_type = td;
erval.structure_ptr = ptr;
return erval;
}
computed_size += encoding_size;
if(!cb || list->count == 0) {
erval.encoded = computed_size;
ASN__ENCODED_OK(erval);
}
/*
* DER mandates dynamic sorting of the SET OF elements
* according to their encodings. Build an array of the
* encoded elements.
*/
encoded_els = (struct _el_buffer *)MALLOC(
list->count * sizeof(encoded_els[0]));
if(encoded_els == NULL) {
erval.encoded = -1;
erval.failed_type = td;
erval.structure_ptr = ptr;
return erval;
}
ASN_DEBUG("Encoding members of %s SET OF", td->name);
/*
* Encode all members.
*/
for(edx = 0; edx < list->count; edx++) {
void *memb_ptr = list->array[edx];
struct _el_buffer *encoded_el = &encoded_els[eels_count];
if(!memb_ptr) continue;
/*
* Prepare space for encoding.
*/
encoded_el->buf = (uint8_t *)MALLOC(max_encoded_len);
if(encoded_el->buf) {
encoded_el->length = 0;
encoded_el->size = max_encoded_len;
} else {
for(edx--; edx >= 0; edx--)
FREEMEM(encoded_els[edx].buf);
FREEMEM(encoded_els);
erval.encoded = -1;
erval.failed_type = td;
erval.structure_ptr = ptr;
return erval;
}
/*
* Encode the member into the prepared space.
*/
erval = der_encoder(elm_type, memb_ptr, 0, elm->tag,
_el_addbytes, encoded_el);
if(erval.encoded == -1) {
for(; edx >= 0; edx--)
FREEMEM(encoded_els[edx].buf);
FREEMEM(encoded_els);
return erval;
}
encoding_size += erval.encoded;
eels_count++;
}
/*
* Sort the encoded elements according to their encoding.
*/
qsort(encoded_els, eels_count, sizeof(encoded_els[0]), _el_buf_cmp);
/*
* Report encoded elements to the application.
* Dispose of temporary sorted members table.
*/
ret = 0;
for(edx = 0; edx < eels_count; edx++) {
struct _el_buffer *encoded_el = &encoded_els[edx];
/* Report encoded chunks to the application */
if(ret == 0
&& cb(encoded_el->buf, encoded_el->length, app_key) < 0)
ret = -1;
FREEMEM(encoded_el->buf);
}
FREEMEM(encoded_els);
if(ret || computed_size != (size_t)encoding_size) {
/*
* Standard callback failed, or
* encoded size is not equal to the computed size.
*/
erval.encoded = -1;
erval.failed_type = td;
erval.structure_ptr = ptr;
} else {
erval.encoded = computed_size;
}
ASN__ENCODED_OK(erval);
}
#undef XER_ADVANCE
#define XER_ADVANCE(num_bytes) do { \
size_t num = num_bytes; \
buf_ptr = ((const char *)buf_ptr) + num;\
size -= num; \
consumed_myself += num; \
} while(0)
/*
* Decode the XER (XML) data.
*/
asn_dec_rval_t
SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **struct_ptr, const char *opt_mname,
const void *buf_ptr, size_t size) {
/*
* Bring closer parts of structure description.
*/
asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
asn_TYPE_member_t *element = td->elements;
const char *elm_tag;
const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
/*
* ... and parts of the structure being constructed.
*/
void *st = *struct_ptr; /* Target structure. */
asn_struct_ctx_t *ctx; /* Decoder context */
asn_dec_rval_t rval; /* Return value from a decoder */
ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
/*
* Create the target structure if it is not present already.
*/
if(st == 0) {
st = *struct_ptr = CALLOC(1, specs->struct_size);
if(st == 0) RETURN(RC_FAIL);
}
/* Which tag is expected for the downstream */
if(specs->as_XMLValueList) {
elm_tag = (specs->as_XMLValueList == 1) ? 0 : "";
} else {
elm_tag = (*element->name)
? element->name : element->type->xml_tag;
}
/*
* Restore parsing context.
*/
ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
/*
* Phases of XER/XML processing:
* Phase 0: Check that the opening tag matches our expectations.
* Phase 1: Processing body and reacting on closing tag.
* Phase 2: Processing inner type.
*/
for(; ctx->phase <= 2;) {
pxer_chunk_type_e ch_type; /* XER chunk type */
ssize_t ch_size; /* Chunk size */
xer_check_tag_e tcv; /* Tag check value */
/*
* Go inside the inner member of a set.
*/
if(ctx->phase == 2) {
asn_dec_rval_t tmprval;
/* Invoke the inner type decoder, m.b. multiple times */
ASN_DEBUG("XER/SET OF element [%s]", elm_tag);
tmprval = element->type->xer_decoder(opt_codec_ctx,
element->type, &ctx->ptr, elm_tag,
buf_ptr, size);
if(tmprval.code == RC_OK) {
asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
if(ASN_SET_ADD(list, ctx->ptr) != 0)
RETURN(RC_FAIL);
ctx->ptr = 0;
XER_ADVANCE(tmprval.consumed);
} else {
XER_ADVANCE(tmprval.consumed);
RETURN(tmprval.code);
}
ctx->phase = 1; /* Back to body processing */
ASN_DEBUG("XER/SET OF phase => %d", ctx->phase);
/* Fall through */
}
/*
* Get the next part of the XML stream.
*/
ch_size = xer_next_token(&ctx->context,
buf_ptr, size, &ch_type);
if(ch_size == -1) {
RETURN(RC_FAIL);
} else {
switch(ch_type) {
case PXER_WMORE:
RETURN(RC_WMORE);
case PXER_COMMENT: /* Got XML comment */
case PXER_TEXT: /* Ignore free-standing text */
XER_ADVANCE(ch_size); /* Skip silently */
continue;
case PXER_TAG:
break; /* Check the rest down there */
}
}
tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
ASN_DEBUG("XER/SET OF: tcv = %d, ph=%d t=%s",
tcv, ctx->phase, xml_tag);
switch(tcv) {
case XCT_CLOSING:
if(ctx->phase == 0) break;
ctx->phase = 0;
/* Fall through */
case XCT_BOTH:
if(ctx->phase == 0) {
/* No more things to decode */
XER_ADVANCE(ch_size);
ctx->phase = 3; /* Phase out */
RETURN(RC_OK);
}
/* Fall through */
case XCT_OPENING:
if(ctx->phase == 0) {
XER_ADVANCE(ch_size);
ctx->phase = 1; /* Processing body phase */
continue;
}
/* Fall through */
case XCT_UNKNOWN_OP:
case XCT_UNKNOWN_BO:
ASN_DEBUG("XER/SET OF: tcv=%d, ph=%d", tcv, ctx->phase);
if(ctx->phase == 1) {
/*
* Process a single possible member.
*/
ctx->phase = 2;
continue;
}
/* Fall through */
default:
break;
}
ASN_DEBUG("Unexpected XML tag in SET OF");
break;
}
ctx->phase = 3; /* "Phase out" on hard failure */
RETURN(RC_FAIL);
}
typedef struct xer_tmp_enc_s {
void *buffer;
size_t offset;
size_t size;
} xer_tmp_enc_t;
static int
SET_OF_encode_xer_callback(const void *buffer, size_t size, void *key) {
xer_tmp_enc_t *t = (xer_tmp_enc_t *)key;
if(t->offset + size >= t->size) {
size_t newsize = (t->size << 2) + size;
void *p = REALLOC(t->buffer, newsize);
if(!p) return -1;
t->buffer = p;
t->size = newsize;
}
memcpy((char *)t->buffer + t->offset, buffer, size);
t->offset += size;
return 0;
}
static int
SET_OF_xer_order(const void *aptr, const void *bptr) {
const xer_tmp_enc_t *a = (const xer_tmp_enc_t *)aptr;
const xer_tmp_enc_t *b = (const xer_tmp_enc_t *)bptr;
size_t minlen = a->offset;
int ret;
if(b->offset < minlen) minlen = b->offset;
/* Well-formed UTF-8 has this nice lexicographical property... */
ret = memcmp(a->buffer, b->buffer, minlen);
if(ret != 0) return ret;
if(a->offset == b->offset)
return 0;
if(a->offset == minlen)
return -1;
return 1;
}
asn_enc_rval_t
SET_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_enc_rval_t er;
asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
asn_TYPE_member_t *elm = td->elements;
asn_anonymous_set_ *list = _A_SET_FROM_VOID(sptr);
const char *mname = specs->as_XMLValueList
? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag);
size_t mlen = mname ? strlen(mname) : 0;
int xcan = (flags & XER_F_CANONICAL);
xer_tmp_enc_t *encs = 0;
size_t encs_count = 0;
void *original_app_key = app_key;
asn_app_consume_bytes_f *original_cb = cb;
int i;
if(!sptr) ASN__ENCODE_FAILED;
if(xcan) {
encs = (xer_tmp_enc_t *)MALLOC(list->count * sizeof(encs[0]));
if(!encs) ASN__ENCODE_FAILED;
cb = SET_OF_encode_xer_callback;
}
er.encoded = 0;
for(i = 0; i < list->count; i++) {
asn_enc_rval_t tmper;
void *memb_ptr = list->array[i];
if(!memb_ptr) continue;
if(encs) {
memset(&encs[encs_count], 0, sizeof(encs[0]));
app_key = &encs[encs_count];
encs_count++;
}
if(mname) {
if(!xcan) ASN__TEXT_INDENT(1, ilevel);
ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
}
if(!xcan && specs->as_XMLValueList == 1)
ASN__TEXT_INDENT(1, ilevel + 1);
tmper = elm->type->xer_encoder(elm->type, memb_ptr,
ilevel + (specs->as_XMLValueList != 2),
flags, cb, app_key);
if(tmper.encoded == -1) {
td = tmper.failed_type;
sptr = tmper.structure_ptr;
goto cb_failed;
}
if(tmper.encoded == 0 && specs->as_XMLValueList) {
const char *name = elm->type->xml_tag;
size_t len = strlen(name);
ASN__CALLBACK3("<", 1, name, len, "/>", 2);
}
if(mname) {
ASN__CALLBACK3("", 2, mname, mlen, ">", 1);
er.encoded += 5;
}
er.encoded += (2 * mlen) + tmper.encoded;
}
if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
if(encs) {
xer_tmp_enc_t *enc = encs;
xer_tmp_enc_t *end = encs + encs_count;
ssize_t control_size = 0;
cb = original_cb;
app_key = original_app_key;
qsort(encs, encs_count, sizeof(encs[0]), SET_OF_xer_order);
for(; enc < end; enc++) {
ASN__CALLBACK(enc->buffer, enc->offset);
FREEMEM(enc->buffer);
enc->buffer = 0;
control_size += enc->offset;
}
assert(control_size == er.encoded);
}
goto cleanup;
cb_failed:
er.encoded = -1;
er.failed_type = td;
er.structure_ptr = sptr;
cleanup:
if(encs) {
while(encs_count-- > 0) {
if(encs[encs_count].buffer)
FREEMEM(encs[encs_count].buffer);
}
FREEMEM(encs);
}
ASN__ENCODED_OK(er);
}
int
SET_OF_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_TYPE_member_t *elm = td->elements;
const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
int ret;
int i;
if(!sptr) return (cb("", 8, app_key) < 0) ? -1 : 0;
/* Dump preamble */
if(cb(td->name, strlen(td->name), app_key) < 0
|| cb(" ::= {", 6, app_key) < 0)
return -1;
for(i = 0; i < list->count; i++) {
const void *memb_ptr = list->array[i];
if(!memb_ptr) continue;
_i_INDENT(1);
ret = elm->type->print_struct(elm->type, memb_ptr,
ilevel + 1, cb, app_key);
if(ret) return ret;
}
ilevel--;
_i_INDENT(1);
return (cb("}", 1, app_key) < 0) ? -1 : 0;
}
void
SET_OF_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
if(td && ptr) {
asn_SET_OF_specifics_t *specs;
asn_TYPE_member_t *elm = td->elements;
asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr);
asn_struct_ctx_t *ctx; /* Decoder context */
int i;
/*
* Could not use set_of_empty() because of (*free)
* incompatibility.
*/
for(i = 0; i < list->count; i++) {
void *memb_ptr = list->array[i];
if(memb_ptr)
ASN_STRUCT_FREE(*elm->type, memb_ptr);
}
list->count = 0; /* No meaningful elements left */
asn_set_empty(list); /* Remove (list->array) */
specs = (asn_SET_OF_specifics_t *)td->specifics;
ctx = (asn_struct_ctx_t *)((char *)ptr + specs->ctx_offset);
if(ctx->ptr) {
ASN_STRUCT_FREE(*elm->type, ctx->ptr);
ctx->ptr = 0;
}
if(!contents_only) {
FREEMEM(ptr);
}
}
}
int
SET_OF_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
asn_TYPE_member_t *elm = td->elements;
asn_constr_check_f *constr;
const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
int i;
if(!sptr) {
ASN__CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
constr = elm->memb_constraints;
if(!constr) constr = elm->type->check_constraints;
/*
* Iterate over the members of an array.
* Validate each in turn, until one fails.
*/
for(i = 0; i < list->count; i++) {
const void *memb_ptr = list->array[i];
int ret;
if(!memb_ptr) continue;
ret = constr(elm->type, memb_ptr, ctfailcb, app_key);
if(ret) return ret;
}
/*
* Cannot inherit it eralier:
* need to make sure we get the updated version.
*/
if(!elm->memb_constraints)
elm->memb_constraints = elm->type->check_constraints;
return 0;
}
asn_dec_rval_t
SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_dec_rval_t rv;
asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
asn_TYPE_member_t *elm = td->elements; /* Single one */
void *st = *sptr;
asn_anonymous_set_ *list;
asn_per_constraint_t *ct;
int repeat = 0;
ssize_t nelems;
if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
ASN__DECODE_FAILED;
/*
* Create the target structure if it is not present already.
*/
if(!st) {
st = *sptr = CALLOC(1, specs->struct_size);
if(!st) ASN__DECODE_FAILED;
}
list = _A_SET_FROM_VOID(st);
/* Figure out which constraints to use */
if(constraints) ct = &constraints->size;
else if(td->per_constraints) ct = &td->per_constraints->size;
else ct = 0;
if(ct && ct->flags & APC_EXTENSIBLE) {
int value = per_get_few_bits(pd, 1);
if(value < 0) ASN__DECODE_STARVED;
if(value) ct = 0; /* Not restricted! */
}
if(ct && ct->effective_bits >= 0) {
/* X.691, #19.5: No length determinant */
nelems = per_get_few_bits(pd, ct->effective_bits);
ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s",
(long)nelems, ct->lower_bound, td->name);
if(nelems < 0) ASN__DECODE_STARVED;
nelems += ct->lower_bound;
} else {
nelems = -1;
}
do {
int i;
if(nelems < 0) {
nelems = uper_get_length(pd,
ct ? ct->effective_bits : -1, &repeat);
ASN_DEBUG("Got to decode %d elements (eff %d)",
(int)nelems, (int)(ct ? ct->effective_bits : -1));
if(nelems < 0) ASN__DECODE_STARVED;
}
for(i = 0; i < nelems; i++) {
void *ptr = 0;
ASN_DEBUG("SET OF %s decoding", elm->type->name);
rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
elm->per_constraints, &ptr, pd);
ASN_DEBUG("%s SET OF %s decoded %d, %p",
td->name, elm->type->name, rv.code, ptr);
if(rv.code == RC_OK) {
if(ASN_SET_ADD(list, ptr) == 0)
continue;
ASN_DEBUG("Failed to add element into %s",
td->name);
/* Fall through */
rv.code = RC_FAIL;
} else {
ASN_DEBUG("Failed decoding %s of %s (SET OF)",
elm->type->name, td->name);
}
if(ptr) ASN_STRUCT_FREE(*elm->type, ptr);
return rv;
}
nelems = -1; /* Allow uper_get_length() */
} while(repeat);
ASN_DEBUG("Decoded %s as SET OF", td->name);
rv.code = RC_OK;
rv.consumed = 0;
return rv;
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/constr_SET_OF.h 0000664 0000000 0000000 00000002054 15245442746 0027110 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _CONSTR_SET_OF_H_
#define _CONSTR_SET_OF_H_
#include
#ifdef __cplusplus
extern "C" {
#endif
typedef const struct asn_SET_OF_specifics_s {
/*
* Target structure description.
*/
int struct_size; /* Size of the target structure. */
int ctx_offset; /* Offset of the asn_struct_ctx_t member */
/* XER-specific stuff */
int as_XMLValueList; /* The member type must be encoded like this */
} asn_SET_OF_specifics_t;
/*
* A set specialized functions dealing with the SET OF type.
*/
asn_struct_free_f SET_OF_free;
asn_struct_print_f SET_OF_print;
asn_constr_check_f SET_OF_constraint;
ber_type_decoder_f SET_OF_decode_ber;
der_type_encoder_f SET_OF_encode_der;
xer_type_decoder_f SET_OF_decode_xer;
xer_type_encoder_f SET_OF_encode_xer;
per_type_decoder_f SET_OF_decode_uper;
per_type_encoder_f SET_OF_encode_uper;
#ifdef __cplusplus
}
#endif
#endif /* _CONSTR_SET_OF_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/constr_TYPE.c 0000664 0000000 0000000 00000003350 15245442746 0026645 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include
/*
* Version of the ASN.1 infrastructure shipped with compiler.
*/
int get_asn1c_environment_version() { return ASN1C_ENVIRONMENT_VERSION; }
static asn_app_consume_bytes_f _print2fp;
/*
* Return the outmost tag of the type.
*/
ber_tlv_tag_t
asn_TYPE_outmost_tag(const asn_TYPE_descriptor_t *type_descriptor,
const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag) {
if(tag_mode)
return tag;
if(type_descriptor->tags_count)
return type_descriptor->tags[0];
return type_descriptor->outmost_tag(type_descriptor, struct_ptr, 0, 0);
}
/*
* Print the target language's structure in human readable form.
*/
int
asn_fprint(FILE *stream, asn_TYPE_descriptor_t *td, const void *struct_ptr) {
if(!stream) stream = stdout;
if(!td || !struct_ptr) {
errno = EINVAL;
return -1;
}
/* Invoke type-specific printer */
if(td->print_struct(td, struct_ptr, 1, _print2fp, stream))
return -1;
/* Terminate the output */
if(_print2fp("\n", 1, stream))
return -1;
return fflush(stream);
}
/* Dump the data into the specified stdio stream */
static int
_print2fp(const void *buffer, size_t size, void *app_key) {
FILE *stream = (FILE *)app_key;
if(fwrite(buffer, 1, size, stream) != size)
return -1;
return 0;
}
/*
* Some compilers do not support variable args macros.
* This function is a replacement of ASN_DEBUG() macro.
*/
void ASN_DEBUG_f(const char *fmt, ...);
void ASN_DEBUG_f(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/constr_TYPE.h 0000664 0000000 0000000 00000015133 15245442746 0026654 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
/*
* This file contains the declaration structure called "ASN.1 Type Definition",
* which holds all information necessary for encoding and decoding routines.
* This structure even contains pointer to these encoding and decoding routines
* for each defined ASN.1 type.
*/
#ifndef _CONSTR_TYPE_H_
#define _CONSTR_TYPE_H_
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
struct asn_TYPE_descriptor_s; /* Forward declaration */
struct asn_TYPE_member_s; /* Forward declaration */
/*
* This type provides the context information for various ASN.1 routines,
* primarily ones doing decoding. A member _asn_ctx of this type must be
* included into certain target language's structures, such as compound types.
*/
typedef struct asn_struct_ctx_s {
short phase; /* Decoding phase */
short step; /* Elementary step of a phase */
int context; /* Other context information */
void *ptr; /* Decoder-specific stuff (stack elements) */
ber_tlv_len_t left; /* Number of bytes left, -1 for indefinite */
} asn_struct_ctx_t;
#include /* Basic Encoding Rules decoder */
#include /* Distinguished Encoding Rules encoder */
#include /* Decoder of XER (XML, text) */
#include /* Encoder into XER (XML, text) */
#include /* Packet Encoding Rules decoder */
#include /* Packet Encoding Rules encoder */
#include /* Subtype constraints support */
/*
* Free the structure according to its specification.
* If (free_contents_only) is set, the wrapper structure itself (struct_ptr)
* will not be freed. (It may be useful in case the structure is allocated
* statically or arranged on the stack, yet its elements are allocated
* dynamically.)
*/
typedef void (asn_struct_free_f)(
struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, int free_contents_only);
#define ASN_STRUCT_FREE(asn_DEF, ptr) (asn_DEF).free_struct(&(asn_DEF),ptr,0)
#define ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF, ptr) \
(asn_DEF).free_struct(&(asn_DEF),ptr,1)
/*
* Print the structure according to its specification.
*/
typedef int (asn_struct_print_f)(
struct asn_TYPE_descriptor_s *type_descriptor,
const void *struct_ptr,
int level, /* Indentation level */
asn_app_consume_bytes_f *callback, void *app_key);
/*
* Return the outmost tag of the type.
* If the type is untagged CHOICE, the dynamic operation is performed.
* NOTE: This function pointer type is only useful internally.
* Do not use it in your application.
*/
typedef ber_tlv_tag_t (asn_outmost_tag_f)(
const struct asn_TYPE_descriptor_s *type_descriptor,
const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag);
/* The instance of the above function type; used internally. */
asn_outmost_tag_f asn_TYPE_outmost_tag;
/*
* The definitive description of the destination language's structure.
*/
typedef struct asn_TYPE_descriptor_s {
const char *name; /* A name of the ASN.1 type. "" in some cases. */
const char *xml_tag; /* Name used in XML tag */
/*
* Generalized functions for dealing with the specific type.
* May be directly invoked by applications.
*/
asn_struct_free_f *free_struct; /* Free the structure */
asn_struct_print_f *print_struct; /* Human readable output */
asn_constr_check_f *check_constraints; /* Constraints validator */
ber_type_decoder_f *ber_decoder; /* Generic BER decoder */
der_type_encoder_f *der_encoder; /* Canonical DER encoder */
xer_type_decoder_f *xer_decoder; /* Generic XER decoder */
xer_type_encoder_f *xer_encoder; /* [Canonical] XER encoder */
per_type_decoder_f *uper_decoder; /* Unaligned PER decoder */
per_type_encoder_f *uper_encoder; /* Unaligned PER encoder */
/***********************************************************************
* Internally useful members. Not to be used by applications directly. *
**********************************************************************/
/*
* Tags that are expected to occur.
*/
asn_outmost_tag_f *outmost_tag; /* */
const ber_tlv_tag_t *tags; /* Effective tags sequence for this type */
int tags_count; /* Number of tags which are expected */
const ber_tlv_tag_t *all_tags; /* Every tag for BER/containment */
int all_tags_count; /* Number of tags */
asn_per_constraints_t *per_constraints; /* PER compiled constraints */
/*
* An ASN.1 production type members (members of SEQUENCE, SET, CHOICE).
*/
struct asn_TYPE_member_s *elements;
int elements_count;
/*
* Additional information describing the type, used by appropriate
* functions above.
*/
const void *specifics;
} asn_TYPE_descriptor_t;
/*
* This type describes an element of the constructed type,
* i.e. SEQUENCE, SET, CHOICE, etc.
*/
enum asn_TYPE_flags_e {
ATF_NOFLAGS,
ATF_POINTER = 0x01, /* Represented by the pointer */
ATF_OPEN_TYPE = 0x02 /* ANY type, without meaningful tag */
};
typedef struct asn_TYPE_member_s {
enum asn_TYPE_flags_e flags; /* Element's presentation flags */
int optional; /* Following optional members, including current */
int memb_offset; /* Offset of the element */
ber_tlv_tag_t tag; /* Outmost (most immediate) tag */
int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */
asn_TYPE_descriptor_t *type; /* Member type descriptor */
asn_constr_check_f *memb_constraints; /* Constraints validator */
asn_per_constraints_t *per_constraints; /* PER compiled constraints */
int (*default_value)(int setval, void **sptr); /* DEFAULT */
const char *name; /* ASN.1 identifier of the element */
} asn_TYPE_member_t;
/*
* BER tag to element number mapping.
*/
typedef struct asn_TYPE_tag2member_s {
ber_tlv_tag_t el_tag; /* Outmost tag of the member */
int el_no; /* Index of the associated member, base 0 */
int toff_first; /* First occurence of the el_tag, relative */
int toff_last; /* Last occurence of the el_tag, relatvie */
} asn_TYPE_tag2member_t;
/*
* This function is a wrapper around (td)->print_struct, which prints out
* the contents of the target language's structure (struct_ptr) into the
* file pointer (stream) in human readable form.
* RETURN VALUES:
* 0: The structure is printed.
* -1: Problem dumping the structure.
* (See also xer_fprint() in xer_encoder.h)
*/
int asn_fprint(FILE *stream, /* Destination stream descriptor */
asn_TYPE_descriptor_t *td, /* ASN.1 type descriptor */
const void *struct_ptr); /* Structure to be printed */
#ifdef __cplusplus
}
#endif
#endif /* _CONSTR_TYPE_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/constraints.c 0000664 0000000 0000000 00000004257 15245442746 0027052 0 ustar 00root root 0000000 0000000 #include "asn_internal.h"
#include "constraints.h"
int
asn_generic_no_constraint(asn_TYPE_descriptor_t *type_descriptor,
const void *struct_ptr, asn_app_constraint_failed_f *cb, void *key) {
(void)type_descriptor; /* Unused argument */
(void)struct_ptr; /* Unused argument */
(void)cb; /* Unused argument */
(void)key; /* Unused argument */
/* Nothing to check */
return 0;
}
int
asn_generic_unknown_constraint(asn_TYPE_descriptor_t *type_descriptor,
const void *struct_ptr, asn_app_constraint_failed_f *cb, void *key) {
(void)type_descriptor; /* Unused argument */
(void)struct_ptr; /* Unused argument */
(void)cb; /* Unused argument */
(void)key; /* Unused argument */
/* Unknown how to check */
return 0;
}
struct errbufDesc {
asn_TYPE_descriptor_t *failed_type;
const void *failed_struct_ptr;
char *errbuf;
size_t errlen;
};
static void
_asn_i_ctfailcb(void *key, asn_TYPE_descriptor_t *td, const void *sptr, const char *fmt, ...) {
struct errbufDesc *arg = key;
va_list ap;
ssize_t vlen;
ssize_t maxlen;
arg->failed_type = td;
arg->failed_struct_ptr = sptr;
maxlen = arg->errlen;
if(maxlen <= 0)
return;
va_start(ap, fmt);
vlen = vsnprintf(arg->errbuf, maxlen, fmt, ap);
va_end(ap);
if(vlen >= maxlen) {
arg->errbuf[maxlen-1] = '\0'; /* Ensuring libc correctness */
arg->errlen = maxlen - 1; /* Not counting termination */
return;
} else if(vlen >= 0) {
arg->errbuf[vlen] = '\0'; /* Ensuring libc correctness */
arg->errlen = vlen; /* Not counting termination */
} else {
/*
* The libc on this system is broken.
*/
vlen = sizeof("") - 1;
maxlen--;
arg->errlen = vlen < maxlen ? vlen : maxlen;
memcpy(arg->errbuf, "", arg->errlen);
arg->errbuf[arg->errlen] = 0;
}
return;
}
int
asn_check_constraints(asn_TYPE_descriptor_t *type_descriptor,
const void *struct_ptr, char *errbuf, size_t *errlen) {
struct errbufDesc arg;
int ret;
arg.failed_type = 0;
arg.failed_struct_ptr = 0;
arg.errbuf = errbuf;
arg.errlen = errlen ? *errlen : 0;
ret = type_descriptor->check_constraints(type_descriptor,
struct_ptr, _asn_i_ctfailcb, &arg);
if(ret == -1 && errlen)
*errlen = arg.errlen;
return ret;
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/constraints.h 0000664 0000000 0000000 00000003651 15245442746 0027054 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2004, 2006 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef ASN1_CONSTRAINTS_VALIDATOR_H
#define ASN1_CONSTRAINTS_VALIDATOR_H
#include /* Platform-dependent types */
#ifdef __cplusplus
extern "C" {
#endif
struct asn_TYPE_descriptor_s; /* Forward declaration */
/*
* Validate the structure according to the ASN.1 constraints.
* If errbuf and errlen are given, they shall be pointing to the appropriate
* buffer space and its length before calling this function. Alternatively,
* they could be passed as NULL's. If constraints validation fails,
* errlen will contain the actual number of bytes taken from the errbuf
* to encode an error message (properly 0-terminated).
*
* RETURN VALUES:
* This function returns 0 in case all ASN.1 constraints are met
* and -1 if one or more constraints were failed.
*/
int
asn_check_constraints(struct asn_TYPE_descriptor_s *type_descriptor,
const void *struct_ptr, /* Target language's structure */
char *errbuf, /* Returned error description */
size_t *errlen /* Length of the error description */
);
/*
* Generic type for constraint checking callback,
* associated with every type descriptor.
*/
typedef int (asn_constr_check_f)(
struct asn_TYPE_descriptor_s *type_descriptor,
const void *struct_ptr,
asn_app_constraint_failed_f *optional_callback, /* Log the error */
void *optional_app_key /* Opaque key passed to a callback */
);
/*******************************
* INTERNALLY USEFUL FUNCTIONS *
*******************************/
asn_constr_check_f asn_generic_no_constraint; /* No constraint whatsoever */
asn_constr_check_f asn_generic_unknown_constraint; /* Not fully supported */
/*
* Invoke the callback with a complete error message.
*/
#define ASN__CTFAIL if(ctfailcb) ctfailcb
#ifdef __cplusplus
}
#endif
#endif /* ASN1_CONSTRAINTS_VALIDATOR_H */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/der_encoder.c 0000664 0000000 0000000 00000011752 15245442746 0026752 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
static ssize_t der_write_TL(ber_tlv_tag_t tag, ber_tlv_len_t len,
asn_app_consume_bytes_f *cb, void *app_key, int constructed);
/*
* The DER encoder of any type.
*/
asn_enc_rval_t
der_encode(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr,
asn_app_consume_bytes_f *consume_bytes, void *app_key) {
ASN_DEBUG("DER encoder invoked for %s",
type_descriptor->name);
/*
* Invoke type-specific encoder.
*/
return type_descriptor->der_encoder(type_descriptor,
struct_ptr, /* Pointer to the destination structure */
0, 0,
consume_bytes, app_key);
}
/*
* Argument type and callback necessary for der_encode_to_buffer().
*/
typedef struct enc_to_buf_arg {
void *buffer;
size_t left;
} enc_to_buf_arg;
static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
enc_to_buf_arg *arg = (enc_to_buf_arg *)key;
if(arg->left < size)
return -1; /* Data exceeds the available buffer size */
memcpy(arg->buffer, buffer, size);
arg->buffer = ((char *)arg->buffer) + size;
arg->left -= size;
return 0;
}
/*
* A variant of the der_encode() which encodes the data into the provided buffer
*/
asn_enc_rval_t
der_encode_to_buffer(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr,
void *buffer, size_t buffer_size) {
enc_to_buf_arg arg;
asn_enc_rval_t ec;
arg.buffer = buffer;
arg.left = buffer_size;
ec = type_descriptor->der_encoder(type_descriptor,
struct_ptr, /* Pointer to the destination structure */
0, 0, encode_to_buffer_cb, &arg);
if(ec.encoded != -1) {
assert(ec.encoded == (ssize_t)(buffer_size - arg.left));
/* Return the encoded contents size */
}
return ec;
}
/*
* Write out leading TL[v] sequence according to the type definition.
*/
ssize_t
der_write_tags(asn_TYPE_descriptor_t *sd,
size_t struct_length,
int tag_mode, int last_tag_form,
ber_tlv_tag_t tag, /* EXPLICIT or IMPLICIT tag */
asn_app_consume_bytes_f *cb,
void *app_key) {
const ber_tlv_tag_t *tags; /* Copy of tags stream */
int tags_count; /* Number of tags */
size_t overall_length;
ssize_t *lens;
int i;
ASN_DEBUG("Writing tags (%s, tm=%d, tc=%d, tag=%s, mtc=%d)",
sd->name, tag_mode, sd->tags_count,
ber_tlv_tag_string(tag),
tag_mode
?(sd->tags_count+1
-((tag_mode == -1) && sd->tags_count))
:sd->tags_count
);
if(tag_mode) {
/*
* Instead of doing shaman dance like we do in ber_check_tags(),
* allocate a small array on the stack
* and initialize it appropriately.
*/
int stag_offset;
ber_tlv_tag_t *tags_buf;
tags_buf = (ber_tlv_tag_t *)alloca((sd->tags_count + 1) * sizeof(ber_tlv_tag_t));
if(!tags_buf) { /* Can fail on !x86 */
errno = ENOMEM;
return -1;
}
tags_count = sd->tags_count
+ 1 /* EXPLICIT or IMPLICIT tag is given */
- ((tag_mode == -1) && sd->tags_count);
/* Copy tags over */
tags_buf[0] = tag;
stag_offset = -1 + ((tag_mode == -1) && sd->tags_count);
for(i = 1; i < tags_count; i++)
tags_buf[i] = sd->tags[i + stag_offset];
tags = tags_buf;
} else {
tags = sd->tags;
tags_count = sd->tags_count;
}
/* No tags to write */
if(tags_count == 0)
return 0;
lens = (ssize_t *)alloca(tags_count * sizeof(lens[0]));
if(!lens) {
errno = ENOMEM;
return -1;
}
/*
* Array of tags is initialized.
* Now, compute the size of the TLV pairs, from right to left.
*/
overall_length = struct_length;
for(i = tags_count - 1; i >= 0; --i) {
lens[i] = der_write_TL(tags[i], overall_length, 0, 0, 0);
if(lens[i] == -1) return -1;
overall_length += lens[i];
lens[i] = overall_length - lens[i];
}
if(!cb) return overall_length - struct_length;
ASN_DEBUG("%s %s TL sequence (%d elements)",
cb?"Encoding":"Estimating", sd->name, tags_count);
/*
* Encode the TL sequence for real.
*/
for(i = 0; i < tags_count; i++) {
ssize_t len;
int _constr;
/* Check if this tag happens to be constructed */
_constr = (last_tag_form || i < (tags_count - 1));
len = der_write_TL(tags[i], lens[i], cb, app_key, _constr);
if(len == -1) return -1;
}
return overall_length - struct_length;
}
static ssize_t
der_write_TL(ber_tlv_tag_t tag, ber_tlv_len_t len,
asn_app_consume_bytes_f *cb, void *app_key,
int constructed) {
uint8_t buf[32];
size_t size = 0;
int buf_size = cb?sizeof(buf):0;
ssize_t tmp;
/* Serialize tag (T from TLV) into possibly zero-length buffer */
tmp = ber_tlv_tag_serialize(tag, buf, buf_size);
if(tmp == -1 || tmp > (ssize_t)sizeof(buf)) return -1;
size += tmp;
/* Serialize length (L from TLV) into possibly zero-length buffer */
tmp = der_tlv_length_serialize(len, buf+size, buf_size?buf_size-size:0);
if(tmp == -1) return -1;
size += tmp;
if(size > sizeof(buf))
return -1;
/*
* If callback is specified, invoke it, and check its return value.
*/
if(cb) {
if(constructed) *buf |= 0x20;
if(cb(buf, size, app_key) < 0)
return -1;
}
return size;
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/der_encoder.h 0000664 0000000 0000000 00000003631 15245442746 0026754 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _DER_ENCODER_H_
#define _DER_ENCODER_H_
#include
#ifdef __cplusplus
extern "C" {
#endif
struct asn_TYPE_descriptor_s; /* Forward declaration */
/*
* The DER encoder of any type. May be invoked by the application.
* The ber_decode() function (ber_decoder.h) is an opposite of der_encode().
*/
asn_enc_rval_t der_encode(struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, /* Structure to be encoded */
asn_app_consume_bytes_f *consume_bytes_cb,
void *app_key /* Arbitrary callback argument */
);
/* A variant of der_encode() which encodes data into the pre-allocated buffer */
asn_enc_rval_t der_encode_to_buffer(
struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, /* Structure to be encoded */
void *buffer, /* Pre-allocated buffer */
size_t buffer_size /* Initial buffer size (maximum) */
);
/*
* Type of the generic DER encoder.
*/
typedef asn_enc_rval_t (der_type_encoder_f)(
struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, /* Structure to be encoded */
int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */
ber_tlv_tag_t tag,
asn_app_consume_bytes_f *consume_bytes_cb, /* Callback */
void *app_key /* Arbitrary callback argument */
);
/*******************************
* INTERNALLY USEFUL FUNCTIONS *
*******************************/
/*
* Write out leading TL[v] sequence according to the type definition.
*/
ssize_t der_write_tags(
struct asn_TYPE_descriptor_s *type_descriptor,
size_t struct_length,
int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */
int last_tag_form, /* {0,!0}: prim, constructed */
ber_tlv_tag_t tag,
asn_app_consume_bytes_f *consume_bytes_cb,
void *app_key
);
#ifdef __cplusplus
}
#endif
#endif /* _DER_ENCODER_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/per_decoder.c 0000664 0000000 0000000 00000004776 15245442746 0026764 0 ustar 00root root 0000000 0000000 #include
#include
#include
/*
* Decode a "Production of a complete encoding", X.691#10.1.
* The complete encoding contains at least one byte, and is an integral
* multiple of 8 bytes.
*/
asn_dec_rval_t
uper_decode_complete(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size) {
asn_dec_rval_t rval;
rval = uper_decode(opt_codec_ctx, td, sptr, buffer, size, 0, 0);
if(rval.consumed) {
/*
* We've always given 8-aligned data,
* so convert bits to integral bytes.
*/
rval.consumed += 7;
rval.consumed >>= 3;
} else if(rval.code == RC_OK) {
if(size) {
if(((const uint8_t *)buffer)[0] == 0) {
rval.consumed = 1; /* 1 byte */
} else {
ASN_DEBUG("Expecting single zeroed byte");
rval.code = RC_FAIL;
}
} else {
/* Must contain at least 8 bits. */
rval.code = RC_WMORE;
}
}
return rval;
}
asn_dec_rval_t
uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits, int unused_bits) {
asn_codec_ctx_t s_codec_ctx;
asn_dec_rval_t rval;
asn_per_data_t pd;
if(skip_bits < 0 || skip_bits > 7
|| unused_bits < 0 || unused_bits > 7
|| (unused_bits > 0 && !size))
ASN__DECODE_FAILED;
/*
* Stack checker requires that the codec context
* must be allocated on the stack.
*/
if(opt_codec_ctx) {
if(opt_codec_ctx->max_stack_size) {
s_codec_ctx = *opt_codec_ctx;
opt_codec_ctx = &s_codec_ctx;
}
} else {
/* If context is not given, be security-conscious anyway */
memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
opt_codec_ctx = &s_codec_ctx;
}
/* Fill in the position indicator */
memset(&pd, 0, sizeof(pd));
pd.buffer = (const uint8_t *)buffer;
pd.nboff = skip_bits;
pd.nbits = 8 * size - unused_bits; /* 8 is CHAR_BIT from */
if(pd.nboff > pd.nbits)
ASN__DECODE_FAILED;
/*
* Invoke type-specific decoder.
*/
if(!td->uper_decoder)
ASN__DECODE_FAILED; /* PER is not compiled in */
rval = td->uper_decoder(opt_codec_ctx, td, 0, sptr, &pd);
if(rval.code == RC_OK) {
/* Return the number of consumed bits */
rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3)
+ pd.nboff - skip_bits;
ASN_DEBUG("PER decoding consumed %ld, counted %ld",
(long)rval.consumed, (long)pd.moved);
assert(rval.consumed == pd.moved);
} else {
/* PER codec is not a restartable */
rval.consumed = 0;
}
return rval;
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/per_decoder.h 0000664 0000000 0000000 00000003300 15245442746 0026747 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2005, 2007 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _PER_DECODER_H_
#define _PER_DECODER_H_
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
struct asn_TYPE_descriptor_s; /* Forward declaration */
/*
* Unaligned PER decoder of a "complete encoding" as per X.691#10.1.
* On success, this call always returns (.consumed >= 1), as per X.691#10.1.3.
*/
asn_dec_rval_t uper_decode_complete(struct asn_codec_ctx_s *opt_codec_ctx,
struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */
void **struct_ptr, /* Pointer to a target structure's pointer */
const void *buffer, /* Data to be decoded */
size_t size /* Size of data buffer */
);
/*
* Unaligned PER decoder of any ASN.1 type. May be invoked by the application.
* WARNING: This call returns the number of BITS read from the stream. Beware.
*/
asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx,
struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */
void **struct_ptr, /* Pointer to a target structure's pointer */
const void *buffer, /* Data to be decoded */
size_t size, /* Size of data buffer */
int skip_bits, /* Number of unused leading bits, 0..7 */
int unused_bits /* Number of unused tailing bits, 0..7 */
);
/*
* Type of the type-specific PER decoder function.
*/
typedef asn_dec_rval_t (per_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx,
struct asn_TYPE_descriptor_s *type_descriptor,
asn_per_constraints_t *constraints,
void **struct_ptr,
asn_per_data_t *per_data
);
#ifdef __cplusplus
}
#endif
#endif /* _PER_DECODER_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/per_encoder.c 0000664 0000000 0000000 00000007165 15245442746 0026771 0 ustar 00root root 0000000 0000000 #include
#include
#include
static asn_enc_rval_t uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *, void *sptr, asn_app_consume_bytes_f *cb, void *app_key);
asn_enc_rval_t
uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
return uper_encode_internal(td, 0, sptr, cb, app_key);
}
/*
* Argument type and callback necessary for uper_encode_to_buffer().
*/
typedef struct enc_to_buf_arg {
void *buffer;
size_t left;
} enc_to_buf_arg;
static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
enc_to_buf_arg *arg = (enc_to_buf_arg *)key;
if(arg->left < size)
return -1; /* Data exceeds the available buffer size */
memcpy(arg->buffer, buffer, size);
arg->buffer = ((char *)arg->buffer) + size;
arg->left -= size;
return 0;
}
asn_enc_rval_t
uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) {
enc_to_buf_arg key;
key.buffer = buffer;
key.left = buffer_size;
if(td) ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name);
return uper_encode_internal(td, 0, sptr, encode_to_buffer_cb, &key);
}
typedef struct enc_dyn_arg {
void *buffer;
size_t length;
size_t allocated;
} enc_dyn_arg;
static int
encode_dyn_cb(const void *buffer, size_t size, void *key) {
enc_dyn_arg *arg = key;
if(arg->length + size >= arg->allocated) {
void *p;
arg->allocated = arg->allocated ? (arg->allocated << 2) : size;
p = REALLOC(arg->buffer, arg->allocated);
if(!p) {
FREEMEM(arg->buffer);
memset(arg, 0, sizeof(*arg));
return -1;
}
arg->buffer = p;
}
memcpy(((char *)arg->buffer) + arg->length, buffer, size);
arg->length += size;
return 0;
}
ssize_t
uper_encode_to_new_buffer(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, void **buffer_r) {
asn_enc_rval_t er;
enc_dyn_arg key;
memset(&key, 0, sizeof(key));
er = uper_encode_internal(td, constraints, sptr, encode_dyn_cb, &key);
switch(er.encoded) {
case -1:
FREEMEM(key.buffer);
return -1;
case 0:
FREEMEM(key.buffer);
key.buffer = MALLOC(1);
if(key.buffer) {
*(char *)key.buffer = '\0';
*buffer_r = key.buffer;
return 1;
} else {
return -1;
}
default:
*buffer_r = key.buffer;
ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
return ((er.encoded + 7) >> 3);
}
}
/*
* Internally useful functions.
*/
/* Flush partially filled buffer */
static int
_uper_encode_flush_outp(asn_per_outp_t *po) {
uint8_t *buf;
if(po->nboff == 0 && po->buffer == po->tmpspace)
return 0;
buf = po->buffer + (po->nboff >> 3);
/* Make sure we account for the last, partially filled */
if(po->nboff & 0x07) {
buf[0] &= 0xff << (8 - (po->nboff & 0x07));
buf++;
}
return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key);
}
static asn_enc_rval_t
uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
asn_per_outp_t po;
asn_enc_rval_t er;
/*
* Invoke type-specific encoder.
*/
if(!td || !td->uper_encoder)
ASN__ENCODE_FAILED; /* PER is not compiled in */
po.buffer = po.tmpspace;
po.nboff = 0;
po.nbits = 8 * sizeof(po.tmpspace);
po.outper = cb;
po.op_key = app_key;
po.flushed_bytes = 0;
er = td->uper_encoder(td, constraints, sptr, &po);
if(er.encoded != -1) {
size_t bits_to_flush;
bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff;
/* Set number of bits encoded to a firm value */
er.encoded = (po.flushed_bytes << 3) + bits_to_flush;
if(_uper_encode_flush_outp(&po))
ASN__ENCODE_FAILED;
}
return er;
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/per_encoder.h 0000664 0000000 0000000 00000004177 15245442746 0026776 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2006, 2007 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _PER_ENCODER_H_
#define _PER_ENCODER_H_
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
struct asn_TYPE_descriptor_s; /* Forward declaration */
/*
* Unaligned PER encoder of any ASN.1 type. May be invoked by the application.
* WARNING: This function returns the number of encoded bits in the .encoded
* field of the return value. Use the following formula to convert to bytes:
* bytes = ((.encoded + 7) / 8)
*/
asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, /* Structure to be encoded */
asn_app_consume_bytes_f *consume_bytes_cb, /* Data collector */
void *app_key /* Arbitrary callback argument */
);
/*
* A variant of uper_encode() which encodes data into the existing buffer
* WARNING: This function returns the number of encoded bits in the .encoded
* field of the return value.
*/
asn_enc_rval_t uper_encode_to_buffer(
struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, /* Structure to be encoded */
void *buffer, /* Pre-allocated buffer */
size_t buffer_size /* Initial buffer size (max) */
);
/*
* A variant of uper_encode_to_buffer() which allocates buffer itself.
* Returns the number of bytes in the buffer or -1 in case of failure.
* WARNING: This function produces a "Production of the complete encoding",
* with length of at least one octet. Contrast this to precise bit-packing
* encoding of uper_encode() and uper_encode_to_buffer().
*/
ssize_t uper_encode_to_new_buffer(
struct asn_TYPE_descriptor_s *type_descriptor,
asn_per_constraints_t *constraints,
void *struct_ptr, /* Structure to be encoded */
void **buffer_r /* Buffer allocated and returned */
);
/*
* Type of the generic PER encoder function.
*/
typedef asn_enc_rval_t (per_type_encoder_f)(
struct asn_TYPE_descriptor_s *type_descriptor,
asn_per_constraints_t *constraints,
void *struct_ptr,
asn_per_outp_t *per_output
);
#ifdef __cplusplus
}
#endif
#endif /* _PER_ENCODER_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/per_opentype.c 0000664 0000000 0000000 00000022536 15245442746 0027214 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2007 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include
#include
typedef struct uper_ugot_key {
asn_per_data_t oldpd; /* Old per data source */
size_t unclaimed;
size_t ot_moved; /* Number of bits moved by OT processing */
int repeat;
} uper_ugot_key;
static int uper_ugot_refill(asn_per_data_t *pd);
static int per_skip_bits(asn_per_data_t *pd, int skip_nbits);
static asn_dec_rval_t uper_sot_suck(asn_codec_ctx_t *, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd);
/*
* Encode an "open type field".
* #10.1, #10.2
*/
int
uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
void *buf;
void *bptr;
ssize_t size;
size_t toGo;
ASN_DEBUG("Open type put %s ...", td->name);
size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
if(size <= 0) return -1;
for(bptr = buf, toGo = size; toGo;) {
ssize_t maySave = uper_put_length(po, toGo);
ASN_DEBUG("Prepending length %d to %s and allowing to save %d",
(int)size, td->name, (int)maySave);
if(maySave < 0) break;
if(per_put_many_bits(po, bptr, maySave * 8)) break;
bptr = (char *)bptr + maySave;
toGo -= maySave;
}
FREEMEM(buf);
if(toGo) return -1;
ASN_DEBUG("Open type put %s of length %ld + overhead (1byte?)",
td->name, (long)size);
return 0;
}
static asn_dec_rval_t
uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_dec_rval_t rv;
ssize_t chunk_bytes;
int repeat;
uint8_t *buf = 0;
size_t bufLen = 0;
size_t bufSize = 0;
asn_per_data_t spd;
size_t padding;
ASN__STACK_OVERFLOW_CHECK(ctx);
ASN_DEBUG("Getting open type %s...", td->name);
do {
chunk_bytes = uper_get_length(pd, -1, &repeat);
if(chunk_bytes < 0) {
FREEMEM(buf);
ASN__DECODE_STARVED;
}
if(bufLen + chunk_bytes > bufSize) {
void *ptr;
bufSize = chunk_bytes + (bufSize << 2);
ptr = REALLOC(buf, bufSize);
if(!ptr) {
FREEMEM(buf);
ASN__DECODE_FAILED;
}
buf = ptr;
}
if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
FREEMEM(buf);
ASN__DECODE_STARVED;
}
bufLen += chunk_bytes;
} while(repeat);
ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
(long)bufLen);
memset(&spd, 0, sizeof(spd));
spd.buffer = buf;
spd.nbits = bufLen << 3;
ASN_DEBUG_INDENT_ADD(+4);
rv = td->uper_decoder(ctx, td, constraints, sptr, &spd);
ASN_DEBUG_INDENT_ADD(-4);
if(rv.code == RC_OK) {
/* Check padding validity */
padding = spd.nbits - spd.nboff;
if ((padding < 8 ||
/* X.691#10.1.3 */
(spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
per_get_few_bits(&spd, padding) == 0) {
/* Everything is cool */
FREEMEM(buf);
return rv;
}
FREEMEM(buf);
if(padding >= 8) {
ASN_DEBUG("Too large padding %d in open type", (int)padding);
ASN__DECODE_FAILED;
} else {
ASN_DEBUG("Non-zero padding");
ASN__DECODE_FAILED;
}
} else {
FREEMEM(buf);
/* rv.code could be RC_WMORE, nonsense in this context */
rv.code = RC_FAIL; /* Noone would give us more */
}
return rv;
}
static asn_dec_rval_t GCC_NOTUSED
uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
uper_ugot_key arg;
asn_dec_rval_t rv;
ssize_t padding;
ASN__STACK_OVERFLOW_CHECK(ctx);
ASN_DEBUG("Getting open type %s from %s", td->name,
per_data_string(pd));
arg.oldpd = *pd;
arg.unclaimed = 0;
arg.ot_moved = 0;
arg.repeat = 1;
pd->refill = uper_ugot_refill;
pd->refill_key = &arg;
pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
pd->moved = 0; /* This now counts the open type size in bits */
ASN_DEBUG_INDENT_ADD(+4);
rv = td->uper_decoder(ctx, td, constraints, sptr, pd);
ASN_DEBUG_INDENT_ADD(-4);
#define UPDRESTOREPD do { \
/* buffer and nboff are valid, preserve them. */ \
pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \
pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \
pd->refill = arg.oldpd.refill; \
pd->refill_key = arg.oldpd.refill_key; \
} while(0)
if(rv.code != RC_OK) {
UPDRESTOREPD;
return rv;
}
ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
per_data_string(pd),
per_data_string(&arg.oldpd),
(int)arg.unclaimed, (int)arg.repeat);
padding = pd->moved % 8;
if(padding) {
int32_t pvalue;
if(padding > 7) {
ASN_DEBUG("Too large padding %d in open type",
(int)padding);
rv.code = RC_FAIL;
UPDRESTOREPD;
return rv;
}
padding = 8 - padding;
ASN_DEBUG("Getting padding of %d bits", (int)padding);
pvalue = per_get_few_bits(pd, padding);
switch(pvalue) {
case -1:
ASN_DEBUG("Padding skip failed");
UPDRESTOREPD;
ASN__DECODE_STARVED;
case 0: break;
default:
ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
(int)padding, (int)pvalue);
UPDRESTOREPD;
ASN__DECODE_FAILED;
}
}
if(pd->nboff != pd->nbits) {
ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
per_data_string(pd), per_data_string(&arg.oldpd));
if(1) {
UPDRESTOREPD;
ASN__DECODE_FAILED;
} else {
arg.unclaimed += pd->nbits - pd->nboff;
}
}
/* Adjust pd back so it points to original data */
UPDRESTOREPD;
/* Skip data not consumed by the decoder */
if(arg.unclaimed) {
ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
switch(per_skip_bits(pd, arg.unclaimed)) {
case -1:
ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
ASN__DECODE_STARVED;
case 0:
ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
break;
default:
/* Padding must be blank */
ASN_DEBUG("Non-blank unconsumed padding");
ASN__DECODE_FAILED;
}
arg.unclaimed = 0;
}
if(arg.repeat) {
ASN_DEBUG("Not consumed the whole thing");
rv.code = RC_FAIL;
return rv;
}
return rv;
}
asn_dec_rval_t
uper_open_type_get(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
}
int
uper_open_type_skip(asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
asn_TYPE_descriptor_t s_td;
asn_dec_rval_t rv;
s_td.name = "";
s_td.uper_decoder = uper_sot_suck;
rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
if(rv.code != RC_OK)
return -1;
else
return 0;
}
/*
* Internal functions.
*/
static asn_dec_rval_t
uper_sot_suck(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_dec_rval_t rv;
(void)ctx;
(void)td;
(void)constraints;
(void)sptr;
while(per_get_few_bits(pd, 24) >= 0);
rv.code = RC_OK;
rv.consumed = pd->moved;
return rv;
}
static int
uper_ugot_refill(asn_per_data_t *pd) {
uper_ugot_key *arg = pd->refill_key;
ssize_t next_chunk_bytes, next_chunk_bits;
ssize_t avail;
asn_per_data_t *oldpd = &arg->oldpd;
ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
(long)pd->moved, (long)oldpd->moved);
/* Advance our position to where pd is */
oldpd->buffer = pd->buffer;
oldpd->nboff = pd->nboff;
oldpd->nbits -= pd->moved - arg->ot_moved;
oldpd->moved += pd->moved - arg->ot_moved;
arg->ot_moved = pd->moved;
if(arg->unclaimed) {
/* Refill the container */
if(per_get_few_bits(oldpd, 1))
return -1;
if(oldpd->nboff == 0) {
assert(0);
return -1;
}
pd->buffer = oldpd->buffer;
pd->nboff = oldpd->nboff - 1;
pd->nbits = oldpd->nbits;
ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
(long)pd->moved);
return 0;
}
if(!arg->repeat) {
ASN_DEBUG("Want more but refill doesn't have it");
return -1;
}
next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
(long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
if(next_chunk_bytes < 0) return -1;
if(next_chunk_bytes == 0) {
pd->refill = 0; /* No more refills, naturally */
assert(!arg->repeat); /* Implementation guarantee */
}
next_chunk_bits = next_chunk_bytes << 3;
avail = oldpd->nbits - oldpd->nboff;
if(avail >= next_chunk_bits) {
pd->nbits = oldpd->nboff + next_chunk_bits;
arg->unclaimed = 0;
ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
(long)next_chunk_bits, (long)oldpd->moved,
(long)oldpd->nboff, (long)oldpd->nbits,
(long)(oldpd->nbits - oldpd->nboff));
} else {
pd->nbits = oldpd->nbits;
arg->unclaimed = next_chunk_bits - avail;
ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
(long)avail, (long)next_chunk_bits,
(long)arg->unclaimed);
}
pd->buffer = oldpd->buffer;
pd->nboff = oldpd->nboff;
ASN_DEBUG("Refilled pd%s old%s",
per_data_string(pd), per_data_string(oldpd));
return 0;
}
static int
per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
int hasNonZeroBits = 0;
while(skip_nbits > 0) {
int skip;
/* per_get_few_bits() is more efficient when nbits <= 24 */
if(skip_nbits < 24)
skip = skip_nbits;
else
skip = 24;
skip_nbits -= skip;
switch(per_get_few_bits(pd, skip)) {
case -1: return -1; /* Starving */
case 0: continue; /* Skipped empty space */
default: hasNonZeroBits = 1; continue;
}
}
return hasNonZeroBits;
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/per_opentype.h 0000664 0000000 0000000 00000001232 15245442746 0027207 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2007 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _PER_OPENTYPE_H_
#define _PER_OPENTYPE_H_
#ifdef __cplusplus
extern "C" {
#endif
asn_dec_rval_t uper_open_type_get(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd);
int uper_open_type_skip(asn_codec_ctx_t *opt_codec_ctx, asn_per_data_t *pd);
int uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po);
#ifdef __cplusplus
}
#endif
#endif /* _PER_OPENTYPE_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/per_support.c 0000664 0000000 0000000 00000026233 15245442746 0027063 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2005-2014 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include
char *
per_data_string(asn_per_data_t *pd) {
static char buf[2][32];
static int n;
n = (n+1) % 2;
snprintf(buf[n], sizeof(buf[n]),
"{m=%ld span %+ld[%d..%d] (%d)}",
(long)pd->moved,
(((long)pd->buffer) & 0xf),
(int)pd->nboff, (int)pd->nbits,
(int)(pd->nbits - pd->nboff));
return buf[n];
}
void
per_get_undo(asn_per_data_t *pd, int nbits) {
if((ssize_t)pd->nboff < nbits) {
assert((ssize_t)pd->nboff < nbits);
} else {
pd->nboff -= nbits;
pd->moved -= nbits;
}
}
/*
* Extract a small number of bits (<= 31) from the specified PER data pointer.
*/
int32_t
per_get_few_bits(asn_per_data_t *pd, int nbits) {
size_t off; /* Next after last bit offset */
ssize_t nleft; /* Number of bits left in this stream */
uint32_t accum;
const uint8_t *buf;
if(nbits < 0)
return -1;
nleft = pd->nbits - pd->nboff;
if(nbits > nleft) {
int32_t tailv, vhead;
if(!pd->refill || nbits > 31) return -1;
/* Accumulate unused bytes before refill */
ASN_DEBUG("Obtain the rest %d bits (want %d)",
(int)nleft, (int)nbits);
tailv = per_get_few_bits(pd, nleft);
if(tailv < 0) return -1;
/* Refill (replace pd contents with new data) */
if(pd->refill(pd))
return -1;
nbits -= nleft;
vhead = per_get_few_bits(pd, nbits);
/* Combine the rest of previous pd with the head of new one */
tailv = (tailv << nbits) | vhead; /* Could == -1 */
return tailv;
}
/*
* Normalize position indicator.
*/
if(pd->nboff >= 8) {
pd->buffer += (pd->nboff >> 3);
pd->nbits -= (pd->nboff & ~0x07);
pd->nboff &= 0x07;
}
pd->moved += nbits;
pd->nboff += nbits;
off = pd->nboff;
buf = pd->buffer;
/*
* Extract specified number of bits.
*/
if(off <= 8)
accum = nbits ? (buf[0]) >> (8 - off) : 0;
else if(off <= 16)
accum = ((buf[0] << 8) + buf[1]) >> (16 - off);
else if(off <= 24)
accum = ((buf[0] << 16) + (buf[1] << 8) + buf[2]) >> (24 - off);
else if(off <= 31)
accum = ((buf[0] << 24) + (buf[1] << 16)
+ (buf[2] << 8) + (buf[3])) >> (32 - off);
else if(nbits <= 31) {
asn_per_data_t tpd = *pd;
/* Here are we with our 31-bits limit plus 1..7 bits offset. */
per_get_undo(&tpd, nbits);
/* The number of available bits in the stream allow
* for the following operations to take place without
* invoking the ->refill() function */
accum = per_get_few_bits(&tpd, nbits - 24) << 24;
accum |= per_get_few_bits(&tpd, 24);
} else {
per_get_undo(pd, nbits);
return -1;
}
accum &= (((uint32_t)1 << nbits) - 1);
ASN_DEBUG(" [PER got %2d<=%2d bits => span %d %+ld[%d..%d]:%02x (%d) => 0x%x]",
(int)nbits, (int)nleft,
(int)pd->moved,
(((long)pd->buffer) & 0xf),
(int)pd->nboff, (int)pd->nbits,
((pd->buffer != NULL)?pd->buffer[0]:0),
(int)(pd->nbits - pd->nboff),
(int)accum);
return accum;
}
/*
* Extract a large number of bits from the specified PER data pointer.
*/
int
per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int alright, int nbits) {
int32_t value;
if(alright && (nbits & 7)) {
/* Perform right alignment of a first few bits */
value = per_get_few_bits(pd, nbits & 0x07);
if(value < 0) return -1;
*dst++ = value; /* value is already right-aligned */
nbits &= ~7;
}
while(nbits) {
if(nbits >= 24) {
value = per_get_few_bits(pd, 24);
if(value < 0) return -1;
*(dst++) = value >> 16;
*(dst++) = value >> 8;
*(dst++) = value;
nbits -= 24;
} else {
value = per_get_few_bits(pd, nbits);
if(value < 0) return -1;
if(nbits & 7) { /* implies left alignment */
value <<= 8 - (nbits & 7),
nbits += 8 - (nbits & 7);
if(nbits > 24)
*dst++ = value >> 24;
}
if(nbits > 16)
*dst++ = value >> 16;
if(nbits > 8)
*dst++ = value >> 8;
*dst++ = value;
break;
}
}
return 0;
}
/*
* Get the length "n" from the stream.
*/
ssize_t
uper_get_length(asn_per_data_t *pd, int ebits, int *repeat) {
ssize_t value;
*repeat = 0;
if(ebits >= 0) return per_get_few_bits(pd, ebits);
value = per_get_few_bits(pd, 8);
if(value < 0) return -1;
if((value & 128) == 0) /* #10.9.3.6 */
return (value & 0x7F);
if((value & 64) == 0) { /* #10.9.3.7 */
value = ((value & 63) << 8) | per_get_few_bits(pd, 8);
if(value < 0) return -1;
return value;
}
value &= 63; /* this is "m" from X.691, #10.9.3.8 */
if(value < 1 || value > 4)
return -1;
*repeat = 1;
return (16384 * value);
}
/*
* Get the normally small length "n".
* This procedure used to decode length of extensions bit-maps
* for SET and SEQUENCE types.
*/
ssize_t
uper_get_nslength(asn_per_data_t *pd) {
ssize_t length;
ASN_DEBUG("Getting normally small length");
if(per_get_few_bits(pd, 1) == 0) {
length = per_get_few_bits(pd, 6) + 1;
if(length <= 0) return -1;
ASN_DEBUG("l=%d", (int)length);
return length;
} else {
int repeat;
length = uper_get_length(pd, -1, &repeat);
if(length >= 0 && !repeat) return length;
return -1; /* Error, or do not support >16K extensions */
}
}
/*
* Get the normally small non-negative whole number.
* X.691, #10.6
*/
ssize_t
uper_get_nsnnwn(asn_per_data_t *pd) {
ssize_t value;
value = per_get_few_bits(pd, 7);
if(value & 64) { /* implicit (value < 0) */
value &= 63;
value <<= 2;
value |= per_get_few_bits(pd, 2);
if(value & 128) /* implicit (value < 0) */
return -1;
if(value == 0)
return 0;
if(value >= 3)
return -1;
value = per_get_few_bits(pd, 8 * value);
return value;
}
return value;
}
/*
* X.691-11/2008, #11.6
* Encoding of a normally small non-negative whole number
*/
int
uper_put_nsnnwn(asn_per_outp_t *po, int n) {
int bytes;
if(n <= 63) {
if(n < 0) return -1;
return per_put_few_bits(po, n, 7);
}
if(n < 256)
bytes = 1;
else if(n < 65536)
bytes = 2;
else if(n < 256 * 65536)
bytes = 3;
else
return -1; /* This is not a "normally small" value */
if(per_put_few_bits(po, bytes, 8))
return -1;
return per_put_few_bits(po, n, 8 * bytes);
}
/* X.691-2008/11, #11.5.6 -> #11.3 */
int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *out_value, int nbits) {
unsigned long lhalf; /* Lower half of the number*/
long half;
if(nbits <= 31) {
half = per_get_few_bits(pd, nbits);
if(half < 0) return -1;
*out_value = half;
return 0;
}
if((size_t)nbits > 8 * sizeof(*out_value))
return -1; /* RANGE */
half = per_get_few_bits(pd, 31);
if(half < 0) return -1;
if(uper_get_constrained_whole_number(pd, &lhalf, nbits - 31))
return -1;
*out_value = ((unsigned long)half << (nbits - 31)) | lhalf;
return 0;
}
/* X.691-2008/11, #11.5.6 -> #11.3 */
int uper_put_constrained_whole_number_s(asn_per_outp_t *po, long v, int nbits) {
/*
* Assume signed number can be safely coerced into
* unsigned of the same range.
* The following testing code will likely be optimized out
* by compiler if it is true.
*/
unsigned long uvalue1 = ULONG_MAX;
long svalue = uvalue1;
unsigned long uvalue2 = svalue;
assert(uvalue1 == uvalue2);
return uper_put_constrained_whole_number_u(po, v, nbits);
}
int uper_put_constrained_whole_number_u(asn_per_outp_t *po, unsigned long v, int nbits) {
if(nbits <= 31) {
return per_put_few_bits(po, v, nbits);
} else {
/* Put higher portion first, followed by lower 31-bit */
if(uper_put_constrained_whole_number_u(po, v >> 31, nbits - 31))
return -1;
return per_put_few_bits(po, v, 31);
}
}
/*
* Put a small number of bits (<= 31).
*/
int
per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
size_t off; /* Next after last bit offset */
size_t omsk; /* Existing last byte meaningful bits mask */
uint8_t *buf;
if(obits <= 0 || obits >= 32) return obits ? -1 : 0;
ASN_DEBUG("[PER put %d bits %x to %p+%d bits]",
obits, (int)bits, po->buffer, (int)po->nboff);
/*
* Normalize position indicator.
*/
if(po->nboff >= 8) {
po->buffer += (po->nboff >> 3);
po->nbits -= (po->nboff & ~0x07);
po->nboff &= 0x07;
}
/*
* Flush whole-bytes output, if necessary.
*/
if(po->nboff + obits > po->nbits) {
int complete_bytes = (po->buffer - po->tmpspace);
ASN_DEBUG("[PER output %ld complete + %ld]",
(long)complete_bytes, (long)po->flushed_bytes);
if(po->outper(po->tmpspace, complete_bytes, po->op_key) < 0)
return -1;
if(po->nboff)
po->tmpspace[0] = po->buffer[0];
po->buffer = po->tmpspace;
po->nbits = 8 * sizeof(po->tmpspace);
po->flushed_bytes += complete_bytes;
}
/*
* Now, due to sizeof(tmpspace), we are guaranteed large enough space.
*/
buf = po->buffer;
omsk = ~((1 << (8 - po->nboff)) - 1);
off = (po->nboff + obits);
/* Clear data of debris before meaningful bits */
bits &= (((uint32_t)1 << obits) - 1);
ASN_DEBUG("[PER out %d %u/%x (t=%d,o=%d) %x&%x=%x]", obits,
(int)bits, (int)bits,
(int)po->nboff, (int)off,
buf[0], (int)(omsk&0xff),
(int)(buf[0] & omsk));
if(off <= 8) /* Completely within 1 byte */
po->nboff = off,
bits <<= (8 - off),
buf[0] = (buf[0] & omsk) | bits;
else if(off <= 16)
po->nboff = off,
bits <<= (16 - off),
buf[0] = (buf[0] & omsk) | (bits >> 8),
buf[1] = bits;
else if(off <= 24)
po->nboff = off,
bits <<= (24 - off),
buf[0] = (buf[0] & omsk) | (bits >> 16),
buf[1] = bits >> 8,
buf[2] = bits;
else if(off <= 31)
po->nboff = off,
bits <<= (32 - off),
buf[0] = (buf[0] & omsk) | (bits >> 24),
buf[1] = bits >> 16,
buf[2] = bits >> 8,
buf[3] = bits;
else {
per_put_few_bits(po, bits >> (obits - 24), 24);
per_put_few_bits(po, bits, obits - 24);
}
ASN_DEBUG("[PER out %u/%x => %02x buf+%ld]",
(int)bits, (int)bits, buf[0],
(long)(po->buffer - po->tmpspace));
return 0;
}
/*
* Output a large number of bits.
*/
int
per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int nbits) {
while(nbits) {
uint32_t value;
if(nbits >= 24) {
value = (src[0] << 16) | (src[1] << 8) | src[2];
src += 3;
nbits -= 24;
if(per_put_few_bits(po, value, 24))
return -1;
} else {
value = src[0];
if(nbits > 8)
value = (value << 8) | src[1];
if(nbits > 16)
value = (value << 8) | src[2];
if(nbits & 0x07)
value >>= (8 - (nbits & 0x07));
if(per_put_few_bits(po, value, nbits))
return -1;
break;
}
}
return 0;
}
/*
* Put the length "n" (or part of it) into the stream.
*/
ssize_t
uper_put_length(asn_per_outp_t *po, size_t length) {
if(length <= 127) /* #10.9.3.6 */
return per_put_few_bits(po, length, 8)
? -1 : (ssize_t)length;
else if(length < 16384) /* #10.9.3.7 */
return per_put_few_bits(po, length|0x8000, 16)
? -1 : (ssize_t)length;
length >>= 14;
if(length > 4) length = 4;
return per_put_few_bits(po, 0xC0 | length, 8)
? -1 : (ssize_t)(length << 14);
}
/*
* Put the normally small length "n" into the stream.
* This procedure used to encode length of extensions bit-maps
* for SET and SEQUENCE types.
*/
int
uper_put_nslength(asn_per_outp_t *po, size_t length) {
if(length <= 64) {
/* #10.9.3.4 */
if(length == 0) return -1;
return per_put_few_bits(po, length-1, 7) ? -1 : 0;
} else {
if(uper_put_length(po, length) != (ssize_t)length) {
/* This might happen in case of >16K extensions */
return -1;
}
}
return 0;
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/per_support.h 0000664 0000000 0000000 00000010257 15245442746 0027067 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2005-2014 Lev Walkin .
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _PER_SUPPORT_H_
#define _PER_SUPPORT_H_
#include /* Platform-specific types */
#ifdef __cplusplus
extern "C" {
#endif
/*
* Pre-computed PER constraints.
*/
typedef const struct asn_per_constraint_s {
enum asn_per_constraint_flags {
APC_UNCONSTRAINED = 0x0, /* No PER visible constraints */
APC_SEMI_CONSTRAINED = 0x1, /* Constrained at "lb" */
APC_CONSTRAINED = 0x2, /* Fully constrained */
APC_EXTENSIBLE = 0x4 /* May have extension */
} flags;
int range_bits; /* Full number of bits in the range */
int effective_bits; /* Effective bits */
long lower_bound; /* "lb" value */
long upper_bound; /* "ub" value */
} asn_per_constraint_t;
typedef const struct asn_per_constraints_s {
struct asn_per_constraint_s value;
struct asn_per_constraint_s size;
int (*value2code)(unsigned int value);
int (*code2value)(unsigned int code);
} asn_per_constraints_t;
/*
* This structure describes a position inside an incoming PER bit stream.
*/
typedef struct asn_per_data_s {
const uint8_t *buffer; /* Pointer to the octet stream */
size_t nboff; /* Bit offset to the meaningful bit */
size_t nbits; /* Number of bits in the stream */
size_t moved; /* Number of bits moved through this bit stream */
int (*refill)(struct asn_per_data_s *);
void *refill_key;
} asn_per_data_t;
/*
* Extract a small number of bits (<= 31) from the specified PER data pointer.
* This function returns -1 if the specified number of bits could not be
* extracted due to EOD or other conditions.
*/
int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits);
/* Undo the immediately preceeding "get_few_bits" operation */
void per_get_undo(asn_per_data_t *per_data, int get_nbits);
/*
* Extract a large number of bits from the specified PER data pointer.
* This function returns -1 if the specified number of bits could not be
* extracted due to EOD or other conditions.
*/
int per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int right_align,
int get_nbits);
/*
* Get the length "n" from the Unaligned PER stream.
*/
ssize_t uper_get_length(asn_per_data_t *pd,
int effective_bound_bits,
int *repeat);
/*
* Get the normally small length "n".
*/
ssize_t uper_get_nslength(asn_per_data_t *pd);
/*
* Get the normally small non-negative whole number.
*/
ssize_t uper_get_nsnnwn(asn_per_data_t *pd);
/* X.691-2008/11, #11.5.6 */
int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *v, int nbits);
/* Non-thread-safe debugging function, don't use it */
char *per_data_string(asn_per_data_t *pd);
/*
* This structure supports forming PER output.
*/
typedef struct asn_per_outp_s {
uint8_t *buffer; /* Pointer into the (tmpspace) */
size_t nboff; /* Bit offset to the meaningful bit */
size_t nbits; /* Number of bits left in (tmpspace) */
uint8_t tmpspace[32]; /* Preliminary storage to hold data */
int (*outper)(const void *data, size_t size, void *op_key);
void *op_key; /* Key for (outper) data callback */
size_t flushed_bytes; /* Bytes already flushed through (outper) */
} asn_per_outp_t;
/* Output a small number of bits (<= 31) */
int per_put_few_bits(asn_per_outp_t *per_data, uint32_t bits, int obits);
/* Output a large number of bits */
int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits);
/* X.691-2008/11, #11.5 */
int uper_put_constrained_whole_number_s(asn_per_outp_t *po, long v, int nbits);
int uper_put_constrained_whole_number_u(asn_per_outp_t *po, unsigned long v, int nbits);
/*
* Put the length "n" to the Unaligned PER stream.
* This function returns the number of units which may be flushed
* in the next units saving iteration.
*/
ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length);
/*
* Put the normally small length "n" to the Unaligned PER stream.
* Returns 0 or -1.
*/
int uper_put_nslength(asn_per_outp_t *po, size_t length);
/*
* Put the normally small non-negative whole number.
*/
int uper_put_nsnnwn(asn_per_outp_t *po, int n);
#ifdef __cplusplus
}
#endif
#endif /* _PER_SUPPORT_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/xer_decoder.c 0000664 0000000 0000000 00000021205 15245442746 0026756 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2004, 2005 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include
#include /* XER/XML parsing support */
/*
* Decode the XER encoding of a given type.
*/
asn_dec_rval_t
xer_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **struct_ptr, const void *buffer, size_t size) {
asn_codec_ctx_t s_codec_ctx;
/*
* Stack checker requires that the codec context
* must be allocated on the stack.
*/
if(opt_codec_ctx) {
if(opt_codec_ctx->max_stack_size) {
s_codec_ctx = *opt_codec_ctx;
opt_codec_ctx = &s_codec_ctx;
}
} else {
/* If context is not given, be security-conscious anyway */
memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
opt_codec_ctx = &s_codec_ctx;
}
/*
* Invoke type-specific decoder.
*/
return td->xer_decoder(opt_codec_ctx, td, struct_ptr, 0, buffer, size);
}
struct xer__cb_arg {
pxml_chunk_type_e chunk_type;
size_t chunk_size;
const void *chunk_buf;
int callback_not_invoked;
};
static int
xer__token_cb(pxml_chunk_type_e type, const void *_chunk_data, size_t _chunk_size, void *key) {
struct xer__cb_arg *arg = (struct xer__cb_arg *)key;
arg->chunk_type = type;
arg->chunk_size = _chunk_size;
arg->chunk_buf = _chunk_data;
arg->callback_not_invoked = 0;
return -1; /* Terminate the XML parsing */
}
/*
* Fetch the next token from the XER/XML stream.
*/
ssize_t
xer_next_token(int *stateContext, const void *buffer, size_t size, pxer_chunk_type_e *ch_type) {
struct xer__cb_arg arg;
int new_stateContext = *stateContext;
ssize_t ret;
arg.callback_not_invoked = 1;
ret = pxml_parse(&new_stateContext, buffer, size, xer__token_cb, &arg);
if(ret < 0) return -1;
if(arg.callback_not_invoked) {
assert(ret == 0); /* No data was consumed */
*ch_type = PXER_WMORE;
return 0; /* Try again with more data */
} else {
assert(arg.chunk_size);
assert(arg.chunk_buf == buffer);
}
/*
* Translate the XML chunk types into more convenient ones.
*/
switch(arg.chunk_type) {
case PXML_TEXT:
*ch_type = PXER_TEXT;
break;
case PXML_TAG:
*ch_type = PXER_WMORE;
return 0; /* Want more */
case PXML_TAG_END:
*ch_type = PXER_TAG;
break;
case PXML_COMMENT:
case PXML_COMMENT_END:
*ch_type = PXER_COMMENT;
break;
}
*stateContext = new_stateContext;
return arg.chunk_size;
}
#define CSLASH 0x2f /* '/' */
#define LANGLE 0x3c /* '<' */
#define RANGLE 0x3e /* '>' */
xer_check_tag_e
xer_check_tag(const void *buf_ptr, int size, const char *need_tag) {
const char *buf = (const char *)buf_ptr;
const char *end;
xer_check_tag_e ct = XCT_OPENING;
if(size < 2 || buf[0] != LANGLE || buf[size-1] != RANGLE) {
if(size >= 2)
ASN_DEBUG("Broken XML tag: \"%c...%c\"",
buf[0], buf[size - 1]);
return XCT_BROKEN;
}
/*
* Determine the tag class.
*/
if(buf[1] == CSLASH) {
buf += 2; /* advance past "" */
size -= 3; /* strip "" and ">" */
ct = XCT_CLOSING;
if(size > 0 && buf[size-1] == CSLASH)
return XCT_BROKEN; /* */
} else {
buf++; /* advance past "<" */
size -= 2; /* strip "<" and ">" */
if(size > 0 && buf[size-1] == CSLASH) {
ct = XCT_BOTH;
size--; /* One more, for "/" */
}
}
/* Sometimes we don't care about the tag */
if(!need_tag || !*need_tag)
return (xer_check_tag_e)(XCT__UNK__MASK | ct);
/*
* Determine the tag name.
*/
for(end = buf + size; buf < end; buf++, need_tag++) {
int b = *buf, n = *need_tag;
if(b != n) {
if(n == 0) {
switch(b) {
case 0x09: case 0x0a: case 0x0c: case 0x0d:
case 0x20:
/* "": whitespace is normal */
return ct;
}
}
return (xer_check_tag_e)(XCT__UNK__MASK | ct);
}
if(b == 0)
return XCT_BROKEN; /* Embedded 0 in buf?! */
}
if(*need_tag)
return (xer_check_tag_e)(XCT__UNK__MASK | ct);
return ct;
}
#undef ADVANCE
#define ADVANCE(num_bytes) do { \
size_t num = (num_bytes); \
buf_ptr = ((const char *)buf_ptr) + num; \
size -= num; \
consumed_myself += num; \
} while(0)
#undef RETURN
#define RETURN(_code) do { \
rval.code = _code; \
rval.consumed = consumed_myself; \
if(rval.code != RC_OK) \
ASN_DEBUG("Failed with %d", rval.code); \
return rval; \
} while(0)
#define XER_GOT_BODY(chunk_buf, chunk_size, size) do { \
ssize_t converted_size = body_receiver \
(struct_key, chunk_buf, chunk_size, \
(size_t)chunk_size < size); \
if(converted_size == -1) RETURN(RC_FAIL); \
if(converted_size == 0 \
&& size == (size_t)chunk_size) \
RETURN(RC_WMORE); \
chunk_size = converted_size; \
} while(0)
#define XER_GOT_EMPTY() do { \
if(body_receiver(struct_key, 0, 0, size > 0) == -1) \
RETURN(RC_FAIL); \
} while(0)
/*
* Generalized function for decoding the primitive values.
*/
asn_dec_rval_t
xer_decode_general(asn_codec_ctx_t *opt_codec_ctx,
asn_struct_ctx_t *ctx, /* Type decoder context */
void *struct_key,
const char *xml_tag, /* Expected XML tag */
const void *buf_ptr, size_t size,
int (*opt_unexpected_tag_decoder)
(void *struct_key, const void *chunk_buf, size_t chunk_size),
ssize_t (*body_receiver)
(void *struct_key, const void *chunk_buf, size_t chunk_size,
int have_more)
) {
asn_dec_rval_t rval;
ssize_t consumed_myself = 0;
(void)opt_codec_ctx;
/*
* Phases of XER/XML processing:
* Phase 0: Check that the opening tag matches our expectations.
* Phase 1: Processing body and reacting on closing tag.
*/
if(ctx->phase > 1) RETURN(RC_FAIL);
for(;;) {
pxer_chunk_type_e ch_type; /* XER chunk type */
ssize_t ch_size; /* Chunk size */
xer_check_tag_e tcv; /* Tag check value */
/*
* Get the next part of the XML stream.
*/
ch_size = xer_next_token(&ctx->context, buf_ptr, size,
&ch_type);
if(ch_size == -1) {
RETURN(RC_FAIL);
} else {
switch(ch_type) {
case PXER_WMORE:
RETURN(RC_WMORE);
case PXER_COMMENT: /* Got XML comment */
ADVANCE(ch_size); /* Skip silently */
continue;
case PXER_TEXT:
if(ctx->phase == 0) {
/*
* We have to ignore whitespace here,
* but in order to be forward compatible
* with EXTENDED-XER (EMBED-VALUES, #25)
* any text is just ignored here.
*/
} else {
XER_GOT_BODY(buf_ptr, ch_size, size);
}
ADVANCE(ch_size);
continue;
case PXER_TAG:
break; /* Check the rest down there */
}
}
assert(ch_type == PXER_TAG && size);
tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
/*
* Phase 0:
* Expecting the opening tag
* for the type being processed.
* Phase 1:
* Waiting for the closing XML tag.
*/
switch(tcv) {
case XCT_BOTH:
if(ctx->phase) break;
/* Finished decoding of an empty element */
XER_GOT_EMPTY();
ADVANCE(ch_size);
ctx->phase = 2; /* Phase out */
RETURN(RC_OK);
case XCT_OPENING:
if(ctx->phase) break;
ADVANCE(ch_size);
ctx->phase = 1; /* Processing body phase */
continue;
case XCT_CLOSING:
if(!ctx->phase) break;
ADVANCE(ch_size);
ctx->phase = 2; /* Phase out */
RETURN(RC_OK);
case XCT_UNKNOWN_BO:
/*
* Certain tags in the body may be expected.
*/
if(opt_unexpected_tag_decoder
&& opt_unexpected_tag_decoder(struct_key,
buf_ptr, ch_size) >= 0) {
/* Tag's processed fine */
ADVANCE(ch_size);
if(!ctx->phase) {
/* We are not expecting
* the closing tag anymore. */
ctx->phase = 2; /* Phase out */
RETURN(RC_OK);
}
continue;
}
/* Fall through */
default:
break; /* Unexpected tag */
}
ASN_DEBUG("Unexpected XML tag (expected \"%s\")", xml_tag);
break; /* Dark and mysterious things have just happened */
}
RETURN(RC_FAIL);
}
size_t
xer_whitespace_span(const void *chunk_buf, size_t chunk_size) {
const char *p = (const char *)chunk_buf;
const char *pend = p + chunk_size;
for(; p < pend; p++) {
switch(*p) {
/* X.693, #8.1.4
* HORISONTAL TAB (9)
* LINE FEED (10)
* CARRIAGE RETURN (13)
* SPACE (32)
*/
case 0x09: case 0x0a: case 0x0d: case 0x20:
continue;
default:
break;
}
break;
}
return (p - (const char *)chunk_buf);
}
/*
* This is a vastly simplified, non-validating XML tree skipper.
*/
int
xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth) {
assert(*depth > 0);
switch(tcv) {
case XCT_BOTH:
case XCT_UNKNOWN_BO:
/* These negate each other. */
return 0;
case XCT_OPENING:
case XCT_UNKNOWN_OP:
++(*depth);
return 0;
case XCT_CLOSING:
case XCT_UNKNOWN_CL:
if(--(*depth) == 0)
return (tcv == XCT_CLOSING) ? 2 : 1;
return 0;
default:
return -1;
}
}
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/xer_decoder.h 0000664 0000000 0000000 00000006520 15245442746 0026766 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _XER_DECODER_H_
#define _XER_DECODER_H_
#include
#ifdef __cplusplus
extern "C" {
#endif
struct asn_TYPE_descriptor_s; /* Forward declaration */
/*
* The XER decoder of any ASN.1 type. May be invoked by the application.
*/
asn_dec_rval_t xer_decode(struct asn_codec_ctx_s *opt_codec_ctx,
struct asn_TYPE_descriptor_s *type_descriptor,
void **struct_ptr, /* Pointer to a target structure's pointer */
const void *buffer, /* Data to be decoded */
size_t size /* Size of data buffer */
);
/*
* Type of the type-specific XER decoder function.
*/
typedef asn_dec_rval_t (xer_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx,
struct asn_TYPE_descriptor_s *type_descriptor,
void **struct_ptr,
const char *opt_mname, /* Member name */
const void *buf_ptr, size_t size
);
/*******************************
* INTERNALLY USEFUL FUNCTIONS *
*******************************/
/*
* Generalized function for decoding the primitive values.
* Used by more specialized functions, such as OCTET_STRING_decode_xer_utf8
* and others. This function should not be used by applications, as its API
* is subject to changes.
*/
asn_dec_rval_t xer_decode_general(asn_codec_ctx_t *opt_codec_ctx,
asn_struct_ctx_t *ctx, /* Type decoder context */
void *struct_key, /* Treated as opaque pointer */
const char *xml_tag, /* Expected XML tag name */
const void *buf_ptr, size_t size,
int (*opt_unexpected_tag_decoder)
(void *struct_key, const void *chunk_buf, size_t chunk_size),
ssize_t (*body_receiver)
(void *struct_key, const void *chunk_buf, size_t chunk_size,
int have_more)
);
/*
* Fetch the next XER (XML) token from the stream.
* The function returns the number of bytes occupied by the chunk type,
* returned in the _ch_type. The _ch_type is only set (and valid) when
* the return value is >= 0.
*/
typedef enum pxer_chunk_type {
PXER_WMORE, /* Chunk type is not clear, more data expected. */
PXER_TAG, /* Complete XER tag */
PXER_TEXT, /* Plain text between XER tags */
PXER_COMMENT /* A comment, may be part of */
} pxer_chunk_type_e;
ssize_t xer_next_token(int *stateContext,
const void *buffer, size_t size, pxer_chunk_type_e *_ch_type);
/*
* This function checks the buffer against the tag name is expected to occur.
*/
typedef enum xer_check_tag {
XCT_BROKEN = 0, /* The tag is broken */
XCT_OPENING = 1, /* This is the tag */
XCT_CLOSING = 2, /* This is the tag */
XCT_BOTH = 3, /* This is the tag */
XCT__UNK__MASK = 4, /* Mask of everything unexpected */
XCT_UNKNOWN_OP = 5, /* Unexpected tag */
XCT_UNKNOWN_CL = 6, /* Unexpected tag */
XCT_UNKNOWN_BO = 7 /* Unexpected tag */
} xer_check_tag_e;
xer_check_tag_e xer_check_tag(const void *buf_ptr, int size,
const char *need_tag);
/*
* Get the number of bytes consisting entirely of XER whitespace characters.
* RETURN VALUES:
* >=0: Number of whitespace characters in the string.
*/
size_t xer_whitespace_span(const void *chunk_buf, size_t chunk_size);
/*
* Skip the series of anticipated extensions.
*/
int xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth);
#ifdef __cplusplus
}
#endif
#endif /* _XER_DECODER_H_ */
asn1tools-0.169.0/examples/benchmarks/c_source/asn1c/generated/xer_encoder.c 0000664 0000000 0000000 00000003005 15245442746 0026766 0 ustar 00root root 0000000 0000000 /*-
* Copyright (c) 2003, 2004 Lev Walkin . All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include
#include