Initial MicroPython v1.21.0 merge; not compiled yet
This commit is contained in:
commit
f2ebe6839c
@ -1,3 +1,9 @@
|
||||
# all: Fix various spelling mistakes found by codespell 2.2.6.
|
||||
cf490a70917a1b2d38ba9b58e763e0837d0f7ca7
|
||||
|
||||
# all: Fix spelling mistakes based on codespell check.
|
||||
b1229efbd1509654dec6053865ab828d769e29db
|
||||
|
||||
# top: Update Python formatting to black "2023 stable style".
|
||||
8b2748269244304854b3462cb8902952b4dcb892
|
||||
|
||||
|
@ -1,135 +0,0 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2014 Coraline Ada Ehmke
|
||||
SPDX-FileCopyrightText: 2019 Kattni Rembor for Adafruit Industries
|
||||
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
# Adafruit Community Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and leaders pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level or type of
|
||||
experience, education, socio-economic status, nationality, personal appearance,
|
||||
race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
We are committed to providing a friendly, safe and welcoming environment for
|
||||
all.
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Be kind and courteous to others
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Collaborating with other community members
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and sexual attention or advances
|
||||
* The use of inappropriate images, including in a community member's avatar
|
||||
* The use of inappropriate language, including in a community member's nickname
|
||||
* Any spamming, flaming, baiting or other attention-stealing behavior
|
||||
* Excessive or unwelcome helping; answering outside the scope of the question
|
||||
asked
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Promoting or spreading disinformation, lies, or conspiracy theories against
|
||||
a person, group, organisation, project, or community
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate
|
||||
|
||||
The goal of the standards and moderation guidelines outlined here is to build
|
||||
and maintain a respectful community. We ask that you don’t just aim to be
|
||||
"technically unimpeachable", but rather try to be your best self.
|
||||
|
||||
We value many things beyond technical expertise, including collaboration and
|
||||
supporting others within our community. Providing a positive experience for
|
||||
other community members can have a much more significant impact than simply
|
||||
providing the correct answer.
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project leaders are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project leaders have the right and responsibility to remove, edit, or
|
||||
reject messages, comments, commits, code, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any community member for other behaviors that they deem
|
||||
inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Moderation
|
||||
|
||||
Instances of behaviors that violate the Adafruit Community Code of Conduct
|
||||
may be reported by any member of the community. Community members are
|
||||
encouraged to report these situations, including situations they witness
|
||||
involving other community members.
|
||||
|
||||
You may report in the following ways:
|
||||
|
||||
In any situation, you may send an email to <support@adafruit.com>.
|
||||
|
||||
On the Adafruit Discord, you may send an open message from any channel
|
||||
to all Community Moderators by tagging @community moderators. You may
|
||||
also send an open message from any channel, or a direct message to
|
||||
@kattni#1507, @tannewt#4653, @danh#1614, @cater#2442,
|
||||
@sommersoft#0222, @Mr. Certainly#0472 or @Andon#8175.
|
||||
|
||||
Email and direct message reports will be kept confidential.
|
||||
|
||||
In situations on Discord where the issue is particularly egregious, possibly
|
||||
illegal, requires immediate action, or violates the Discord terms of service,
|
||||
you should also report the message directly to Discord.
|
||||
|
||||
These are the steps for upholding our community’s standards of conduct.
|
||||
|
||||
1. Any member of the community may report any situation that violates the
|
||||
Adafruit Community Code of Conduct. All reports will be reviewed and
|
||||
investigated.
|
||||
2. If the behavior is an egregious violation, the community member who
|
||||
committed the violation may be banned immediately, without warning.
|
||||
3. Otherwise, moderators will first respond to such behavior with a warning.
|
||||
4. Moderators follow a soft "three strikes" policy - the community member may
|
||||
be given another chance, if they are receptive to the warning and change their
|
||||
behavior.
|
||||
5. If the community member is unreceptive or unreasonable when warned by a
|
||||
moderator, or the warning goes unheeded, they may be banned for a first or
|
||||
second offense. Repeated offenses will result in the community member being
|
||||
banned.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct and the enforcement policies listed above apply to all
|
||||
Adafruit Community venues. This includes but is not limited to any community
|
||||
spaces (both public and private), the entire Adafruit Discord server, and
|
||||
Adafruit GitHub repositories. Examples of Adafruit Community spaces include
|
||||
but are not limited to meet-ups, audio chats on the Adafruit Discord, or
|
||||
interaction at a conference.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. As a community
|
||||
member, you are representing our community, and are expected to behave
|
||||
accordingly.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
|
||||
version 1.4, available at
|
||||
<https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>,
|
||||
and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html).
|
||||
|
||||
For other projects adopting the Adafruit Community Code of
|
||||
Conduct, please contact the maintainers of those projects for enforcement.
|
||||
If you wish to use this code of conduct for your own project, consider
|
||||
explicitly mentioning your moderation policy or making a copy with your
|
||||
own moderation policy so as to avoid confusion.
|
@ -24,7 +24,7 @@ Functions
|
||||
|
||||
.. function:: mem_alloc()
|
||||
|
||||
Return the number of bytes of heap RAM that are allocated.
|
||||
Return the number of bytes of heap RAM that are allocated by Python code.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
@ -33,8 +33,8 @@ Functions
|
||||
|
||||
.. function:: mem_free()
|
||||
|
||||
Return the number of bytes of available heap RAM, or -1 if this amount
|
||||
is not known.
|
||||
Return the number of bytes of heap RAM that is available for Python
|
||||
code to allocate, or -1 if this amount is not known.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
106
docs/library/gzip.rst
Normal file
106
docs/library/gzip.rst
Normal file
@ -0,0 +1,106 @@
|
||||
:mod:`gzip` -- gzip compression & decompression
|
||||
===============================================
|
||||
|
||||
.. module:: gzip
|
||||
:synopsis: gzip compression & decompression
|
||||
|
||||
|see_cpython_module| :mod:`python:gzip`.
|
||||
|
||||
This module allows compression and decompression of binary data with the
|
||||
`DEFLATE algorithm <https://en.wikipedia.org/wiki/DEFLATE>`_ used by the gzip
|
||||
file format.
|
||||
|
||||
.. note:: Prefer to use :class:`deflate.DeflateIO` instead of the functions in this
|
||||
module as it provides a streaming interface to compression and decompression
|
||||
which is convenient and more memory efficient when working with reading or
|
||||
writing compressed data to a file, socket, or stream.
|
||||
|
||||
**Availability:**
|
||||
|
||||
* This module is **not present by default** in official MicroPython firmware
|
||||
releases as it duplicates functionality available in the :mod:`deflate
|
||||
<deflate>` module.
|
||||
|
||||
* A copy of this module can be installed (or frozen)
|
||||
from :term:`micropython-lib` (`source <https://github.com/micropython/micropython-lib/blob/master/python-stdlib/gzip/gzip.py>`_).
|
||||
See :ref:`packages` for more information. This documentation describes that module.
|
||||
|
||||
* Compression support will only be available if compression support is enabled
|
||||
in the built-in :mod:`deflate <deflate>` module.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: open(filename, mode, /)
|
||||
|
||||
Wrapper around built-in :func:`open` returning a GzipFile instance.
|
||||
|
||||
.. function:: decompress(data, /)
|
||||
|
||||
Decompresses *data* into a bytes object.
|
||||
|
||||
.. function:: compress(data, /)
|
||||
|
||||
Compresses *data* into a bytes object.
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
||||
.. class:: GzipFile(*, fileobj, mode)
|
||||
|
||||
This class can be used to wrap a *fileobj* which is any
|
||||
:term:`stream-like <stream>` object such as a file, socket, or stream
|
||||
(including :class:`io.BytesIO`). It is itself a stream and implements the
|
||||
standard read/readinto/write/close methods.
|
||||
|
||||
When the *mode* argument is ``"rb"``, reads from the GzipFile instance will
|
||||
decompress the data in the underlying stream and return decompressed data.
|
||||
|
||||
If compression support is enabled then the *mode* argument can be set to
|
||||
``"wb"``, and writes to the GzipFile instance will be compressed and written
|
||||
to the underlying stream.
|
||||
|
||||
By default the GzipFile class will read and write data using the gzip file
|
||||
format, including a header and footer with checksum and a window size of 512
|
||||
bytes.
|
||||
|
||||
The **file**, **compresslevel**, and **mtime** arguments are not
|
||||
supported. **fileobj** and **mode** must always be specified as keyword
|
||||
arguments.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
A typical use case for :class:`gzip.GzipFile` is to read or write a compressed
|
||||
file from storage:
|
||||
|
||||
.. code:: python
|
||||
|
||||
import gzip
|
||||
|
||||
# Reading:
|
||||
with open("data.gz", "rb") as f:
|
||||
with gzip.GzipFile(fileobj=f, mode="rb") as g:
|
||||
# Use g.read(), g.readinto(), etc.
|
||||
|
||||
# Same, but using gzip.open:
|
||||
with gzip.open("data.gz", "rb") as f:
|
||||
# Use f.read(), f.readinto(), etc.
|
||||
|
||||
# Writing:
|
||||
with open("data.gz", "wb") as f:
|
||||
with gzip.GzipFile(fileobj=f, mode="wb") as g:
|
||||
# Use g.write(...) etc
|
||||
|
||||
# Same, but using gzip.open:
|
||||
with gzip.open("data.gz", "wb") as f:
|
||||
# Use f.write(...) etc
|
||||
|
||||
# Write a dictionary as JSON in gzip format, with a
|
||||
# small (64 byte) window size.
|
||||
config = { ... }
|
||||
with gzip.open("config.gz", "wb") as f:
|
||||
json.dump(config, f)
|
||||
|
||||
For guidance on working with gzip sources and choosing the window size see the
|
||||
note at the :ref:`end of the deflate documentation <deflate_wbits>`.
|
38
docs/library/platform.rst
Normal file
38
docs/library/platform.rst
Normal file
@ -0,0 +1,38 @@
|
||||
:mod:`platform` -- access to underlying platform’s identifying data
|
||||
===================================================================
|
||||
|
||||
.. module:: platform
|
||||
:synopsis: access to underlying platform’s identifying data
|
||||
|
||||
|see_cpython_module| :mod:`python:platform`.
|
||||
|
||||
This module tries to retrieve as much platform-identifying data as possible. It
|
||||
makes this information available via function APIs.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: platform()
|
||||
|
||||
Returns a string identifying the underlying platform. This string is composed
|
||||
of several substrings in the following order, delimited by dashes (``-``):
|
||||
|
||||
- the name of the platform system (e.g. Unix, Windows or MicroPython)
|
||||
- the MicroPython version
|
||||
- the architecture of the platform
|
||||
- the version of the underlying platform
|
||||
- the concatenation of the name of the libc that MicroPython is linked to
|
||||
and its corresponding version.
|
||||
|
||||
For example, this could be
|
||||
``"MicroPython-1.20.0-xtensa-IDFv4.2.4-with-newlib3.0.0"``.
|
||||
|
||||
.. function:: python_compiler()
|
||||
|
||||
Returns a string identifying the compiler used for compiling MicroPython.
|
||||
|
||||
.. function:: libc_ver()
|
||||
|
||||
Returns a tuple of strings *(lib, version)*, where *lib* is the name of the
|
||||
libc that MicroPython is linked to, and *version* the corresponding version
|
||||
of this libc.
|
@ -33,6 +33,7 @@ Constants
|
||||
|
||||
* *name* - string "circuitpython"
|
||||
* *version* - tuple (major, minor, micro), e.g. (1, 7, 0)
|
||||
* *_machine* - string describing the underlying machine
|
||||
* *_mpy* - supported mpy file-format version (optional attribute)
|
||||
|
||||
This object is the recommended way to distinguish CircuitPython from other
|
||||
|
@ -32,7 +32,7 @@ Glossary
|
||||
|
||||
callee-owned tuple
|
||||
This is a MicroPython-specific construct where, for efficiency
|
||||
reasons, some built-in functions or methods may re-use the same
|
||||
reasons, some built-in functions or methods may reuse the same
|
||||
underlying tuple object to return data. This avoids having to allocate
|
||||
a new tuple for every call, and reduces heap fragmentation. Programs
|
||||
should not hold references to callee-owned tuples and instead only
|
||||
@ -120,7 +120,7 @@ Glossary
|
||||
<https://github.com/micropython/micropython-lib>`_ which provides
|
||||
implementations for many modules from CPython's standard library.
|
||||
|
||||
Some of the modules are are implemented in pure Python, and are able to
|
||||
Some of the modules are implemented in pure Python, and are able to
|
||||
be used on all ports. However, the majority of these modules use
|
||||
:term:`FFI` to access operating system functionality, and as such can
|
||||
only be used on the :term:`MicroPython Unix port` (with limited support
|
||||
@ -158,8 +158,10 @@ Glossary
|
||||
network-capable boards, and internally by tools such
|
||||
as :term:`mpremote`.
|
||||
|
||||
See :ref:`packages` for more information on using ``mip``.
|
||||
|
||||
mpremote
|
||||
A tool for interacting with a MicroPython device.
|
||||
A tool for interacting with a MicroPython device. See :ref:`mpremote`.
|
||||
|
||||
.mpy file
|
||||
The output of the :term:`cross-compiler`. A compiled form of a
|
||||
|
74
examples/natmod/README.md
Normal file
74
examples/natmod/README.md
Normal file
@ -0,0 +1,74 @@
|
||||
# Dynamic Native Modules
|
||||
|
||||
Dynamic Native Modules are .mpy files that contain native machine code from a
|
||||
language other than Python. For more info see [the documentation]
|
||||
(https://docs.micropython.org/en/latest/develop/natmod.html).
|
||||
|
||||
This should not be confused with [User C Modules]
|
||||
(https://docs.micropython.org/en/latest/develop/cmodules.html) which are a
|
||||
mechanism to add additional out-of-tree modules into the firmware build.
|
||||
|
||||
## Examples
|
||||
|
||||
This directory contains several examples of writing dynamic native modules, in
|
||||
two main categories:
|
||||
|
||||
1. Feature examples.
|
||||
|
||||
* `features0` - A module containing a single "factorial" function which
|
||||
demonstrates working with integers.
|
||||
|
||||
* `features1` - A module that demonstrates some common tasks:
|
||||
- defining simple functions exposed to Python
|
||||
- defining local, helper C functions
|
||||
- defining constant integers and strings exposed to Python
|
||||
- getting and creating integer objects
|
||||
- creating Python lists
|
||||
- raising exceptions
|
||||
- allocating memory
|
||||
- BSS and constant data (rodata)
|
||||
- relocated pointers in rodata
|
||||
|
||||
* `features2` - This is a hybrid module containing both Python and C code,
|
||||
and additionally the C code is spread over multiple files. It also
|
||||
demonstrates using floating point (only when the target supports
|
||||
hardware floating point).
|
||||
|
||||
* `features3` - A module that shows how to use types, constant objects,
|
||||
and creating dictionary instances.
|
||||
|
||||
* `features4` - A module that demonstrates how to define a class.
|
||||
|
||||
2. Dynamic version of existing built-ins.
|
||||
|
||||
This provides a way to add missing functionality to firmware that doesn't
|
||||
include certain built-in modules. See the `heapq`, `random`, `re`,
|
||||
`deflate`, `btree`, and `framebuf` directories.
|
||||
|
||||
So for example, if your firmware was compiled with `MICROPY_PY_FRAMEBUF`
|
||||
disabled (e.g. to save flash space), then it would not include the
|
||||
`framebuf` module. The `framebuf` native module provides a way to add the
|
||||
`framebuf` module dynamically.
|
||||
|
||||
The way these work is they define a dynamic native module which
|
||||
`#include`'s the original module and then does the necessary
|
||||
initialisation of the module's globals dict.
|
||||
|
||||
## Build instructions
|
||||
|
||||
To compile an example, you need to have the same toolchain available as
|
||||
required for your target port. e.g. `arm-none-eabi-gcc` for any ARM Cortex M
|
||||
target. See the port instructions for details.
|
||||
|
||||
You also need to have the `pyelftools` Python package available, either via
|
||||
your system package manager or installed from PyPI in a virtual environment
|
||||
with `pip`.
|
||||
|
||||
Each example provides a Makefile. You should specify the `ARCH` argument to
|
||||
make (one of x86, x64, armv6m, armv7m, xtensa, xtensawin):
|
||||
|
||||
```
|
||||
$ cd features0
|
||||
$ make ARCH=armv7m
|
||||
$ mpremote cp features0.mpy :
|
||||
```
|
@ -2,10 +2,10 @@
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module (different to built-in uzlib so it can coexist)
|
||||
MOD = uzlib_$(ARCH)
|
||||
MOD = deflate_$(ARCH)
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = uzlib.c
|
||||
SRC = deflate.c
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
70
examples/natmod/deflate/deflate.c
Normal file
70
examples/natmod/deflate/deflate.c
Normal file
@ -0,0 +1,70 @@
|
||||
#define MICROPY_PY_DEFLATE (1)
|
||||
#define MICROPY_PY_DEFLATE_COMPRESS (1)
|
||||
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
#if !defined(__linux__)
|
||||
void *memcpy(void *dst, const void *src, size_t n) {
|
||||
return mp_fun_table.memmove_(dst, src, n);
|
||||
}
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
return mp_fun_table.memset_(s, c, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_obj_full_type_t deflateio_type;
|
||||
|
||||
#include "extmod/moddeflate.c"
|
||||
|
||||
// Re-implemented from py/stream.c, not yet available in dynruntime.h.
|
||||
mp_obj_t mp_stream_close(mp_obj_t stream) {
|
||||
const mp_stream_p_t *stream_p = mp_get_stream(stream);
|
||||
int error;
|
||||
mp_uint_t res = stream_p->ioctl(stream, MP_STREAM_CLOSE, 0, &error);
|
||||
if (res == MP_STREAM_ERROR) {
|
||||
mp_raise_OSError(error);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_close_obj, mp_stream_close);
|
||||
|
||||
// Re-implemented from py/stream.c, not yet available in dynruntime.h.
|
||||
STATIC mp_obj_t mp_stream___exit__(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
return mp_stream_close(args[0]);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream___exit___obj, 4, 4, mp_stream___exit__);
|
||||
|
||||
// Re-implemented from obj.c, not yet available in dynruntime.h.
|
||||
mp_obj_t mp_identity(mp_obj_t self) {
|
||||
return self;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity);
|
||||
|
||||
mp_map_elem_t deflateio_locals_dict_table[7];
|
||||
STATIC MP_DEFINE_CONST_DICT(deflateio_locals_dict, deflateio_locals_dict_table);
|
||||
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
deflateio_type.base.type = mp_fun_table.type_type;
|
||||
deflateio_type.name = MP_QSTR_DeflateIO;
|
||||
MP_OBJ_TYPE_SET_SLOT(&deflateio_type, make_new, &deflateio_make_new, 0);
|
||||
MP_OBJ_TYPE_SET_SLOT(&deflateio_type, protocol, &deflateio_stream_p, 1);
|
||||
deflateio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) };
|
||||
deflateio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) };
|
||||
deflateio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) };
|
||||
deflateio_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_OBJ_FROM_PTR(&mp_stream_write_obj) };
|
||||
deflateio_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_OBJ_FROM_PTR(&mp_stream_close_obj) };
|
||||
deflateio_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR___enter__), MP_OBJ_FROM_PTR(&mp_identity_obj) };
|
||||
deflateio_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR___exit__), MP_OBJ_FROM_PTR(&mp_stream___exit___obj) };
|
||||
MP_OBJ_TYPE_SET_SLOT(&deflateio_type, locals_dict, (void*)&deflateio_locals_dict, 2);
|
||||
|
||||
mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_deflate));
|
||||
mp_store_global(MP_QSTR_DeflateIO, MP_OBJ_FROM_PTR(&deflateio_type));
|
||||
mp_store_global(MP_QSTR_RAW, MP_OBJ_NEW_SMALL_INT(DEFLATEIO_FORMAT_RAW));
|
||||
mp_store_global(MP_QSTR_ZLIB, MP_OBJ_NEW_SMALL_INT(DEFLATEIO_FORMAT_ZLIB));
|
||||
mp_store_global(MP_QSTR_GZIP, MP_OBJ_NEW_SMALL_INT(DEFLATEIO_FORMAT_GZIP));
|
||||
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -88,7 +88,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
|
||||
// This must be first, it sets up the globals dict and other things
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
// Messages can be printed as usually
|
||||
// Messages can be printed as usual
|
||||
mp_printf(&mp_plat_print, "initialising module self=%p\n", self);
|
||||
|
||||
// Make the functions available in the module's namespace
|
||||
|
@ -1,5 +1,7 @@
|
||||
# This Python code will be merged with the C code in main.c
|
||||
|
||||
# ruff: noqa: F821 - this file is evaluated with C-defined names in scope
|
||||
|
||||
import array
|
||||
|
||||
|
||||
|
14
examples/natmod/features4/Makefile
Normal file
14
examples/natmod/features4/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
# Location of top-level MicroPython directory
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module
|
||||
MOD = features4
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = features4.c
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
||||
|
||||
# Include to get the rules for compiling and linking the module
|
||||
include $(MPY_DIR)/py/dynruntime.mk
|
73
examples/natmod/features4/features4.c
Normal file
73
examples/natmod/features4/features4.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
This example extends on features0 but demonstrates how to define a class.
|
||||
|
||||
The Factorial class constructor takes an integer, and then the calculate
|
||||
method can be called to get the factorial.
|
||||
|
||||
>>> import features4
|
||||
>>> f = features4.Factorial(4)
|
||||
>>> f.calculate()
|
||||
24
|
||||
*/
|
||||
|
||||
// Include the header file to get access to the MicroPython API
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
// This is type(Factorial)
|
||||
mp_obj_full_type_t mp_type_factorial;
|
||||
|
||||
// This is the internal state of a Factorial instance.
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
mp_int_t n;
|
||||
} mp_obj_factorial_t;
|
||||
|
||||
// Essentially Factorial.__new__ (but also kind of __init__).
|
||||
// Takes a single argument (the number to find the factorial of)
|
||||
STATIC mp_obj_t factorial_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, 1, false);
|
||||
|
||||
mp_obj_factorial_t *o = mp_obj_malloc(mp_obj_factorial_t, type);
|
||||
o->n = mp_obj_get_int(args_in[0]);
|
||||
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_int_t factorial_helper(mp_int_t x) {
|
||||
if (x == 0) {
|
||||
return 1;
|
||||
}
|
||||
return x * factorial_helper(x - 1);
|
||||
}
|
||||
|
||||
// Implements Factorial.calculate()
|
||||
STATIC mp_obj_t factorial_calculate(mp_obj_t self_in) {
|
||||
mp_obj_factorial_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_obj_new_int(factorial_helper(self->n));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_calculate_obj, factorial_calculate);
|
||||
|
||||
// Locals dict for the Factorial type (will have a single method, calculate,
|
||||
// added in mpy_init).
|
||||
mp_map_elem_t factorial_locals_dict_table[1];
|
||||
STATIC MP_DEFINE_CONST_DICT(factorial_locals_dict, factorial_locals_dict_table);
|
||||
|
||||
// This is the entry point and is called when the module is imported
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
// This must be first, it sets up the globals dict and other things
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
// Initialise the type.
|
||||
mp_type_factorial.base.type = (void*)&mp_type_type;
|
||||
mp_type_factorial.flags = MP_TYPE_FLAG_NONE;
|
||||
mp_type_factorial.name = MP_QSTR_Factorial;
|
||||
MP_OBJ_TYPE_SET_SLOT(&mp_type_factorial, make_new, factorial_make_new, 0);
|
||||
factorial_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_calculate), MP_OBJ_FROM_PTR(&factorial_calculate_obj) };
|
||||
MP_OBJ_TYPE_SET_SLOT(&mp_type_factorial, locals_dict, (void*)&factorial_locals_dict, 1);
|
||||
|
||||
// Make the Factorial type available on the module.
|
||||
mp_store_global(MP_QSTR_Factorial, MP_OBJ_FROM_PTR(&mp_type_factorial));
|
||||
|
||||
// This must be last, it restores the globals dict
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
# Location of top-level MicroPython directory
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module (different to built-in urandom so it can coexist)
|
||||
MOD = urandom_$(ARCH)
|
||||
# Name of module (different to built-in heapq so it can coexist)
|
||||
MOD = heapq_$(ARCH)
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = urandom.c
|
||||
SRC = heapq.c
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
16
examples/natmod/heapq/heapq.c
Normal file
16
examples/natmod/heapq/heapq.c
Normal file
@ -0,0 +1,16 @@
|
||||
#define MICROPY_PY_HEAPQ (1)
|
||||
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
#include "extmod/modheapq.c"
|
||||
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_heapq));
|
||||
mp_store_global(MP_QSTR_heappush, MP_OBJ_FROM_PTR(&mod_heapq_heappush_obj));
|
||||
mp_store_global(MP_QSTR_heappop, MP_OBJ_FROM_PTR(&mod_heapq_heappop_obj));
|
||||
mp_store_global(MP_QSTR_heapify, MP_OBJ_FROM_PTR(&mod_heapq_heapify_obj));
|
||||
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
# Location of top-level MicroPython directory
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module (different to built-in uheapq so it can coexist)
|
||||
MOD = uheapq_$(ARCH)
|
||||
# Name of module (different to built-in random so it can coexist)
|
||||
MOD = random_$(ARCH)
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = uheapq.c
|
||||
SRC = random.c
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
33
examples/natmod/random/random.c
Normal file
33
examples/natmod/random/random.c
Normal file
@ -0,0 +1,33 @@
|
||||
#define MICROPY_PY_RANDOM (1)
|
||||
#define MICROPY_PY_RANDOM_EXTRA_FUNCS (1)
|
||||
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
// Dynamic native modules don't support a data section so these must go in the BSS
|
||||
uint32_t yasmarang_pad, yasmarang_n, yasmarang_d;
|
||||
uint8_t yasmarang_dat;
|
||||
|
||||
#include "extmod/modrandom.c"
|
||||
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
yasmarang_pad = 0xeda4baba;
|
||||
yasmarang_n = 69;
|
||||
yasmarang_d = 233;
|
||||
|
||||
mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_random));
|
||||
mp_store_global(MP_QSTR_getrandbits, MP_OBJ_FROM_PTR(&mod_random_getrandbits_obj));
|
||||
mp_store_global(MP_QSTR_seed, MP_OBJ_FROM_PTR(&mod_random_seed_obj));
|
||||
#if MICROPY_PY_RANDOM_EXTRA_FUNCS
|
||||
mp_store_global(MP_QSTR_randrange, MP_OBJ_FROM_PTR(&mod_random_randrange_obj));
|
||||
mp_store_global(MP_QSTR_randint, MP_OBJ_FROM_PTR(&mod_random_randint_obj));
|
||||
mp_store_global(MP_QSTR_choice, MP_OBJ_FROM_PTR(&mod_random_choice_obj));
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_store_global(MP_QSTR_random, MP_OBJ_FROM_PTR(&mod_random_random_obj));
|
||||
mp_store_global(MP_QSTR_uniform, MP_OBJ_FROM_PTR(&mod_random_uniform_obj));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
# Location of top-level MicroPython directory
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module (different to built-in ure so it can coexist)
|
||||
MOD = ure_$(ARCH)
|
||||
# Name of module (different to built-in re so it can coexist)
|
||||
MOD = re_$(ARCH)
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = ure.c
|
||||
SRC = re.c
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
@ -1,8 +1,8 @@
|
||||
#define MICROPY_STACK_CHECK (1)
|
||||
#define MICROPY_PY_URE (1)
|
||||
#define MICROPY_PY_URE_MATCH_GROUPS (1)
|
||||
#define MICROPY_PY_URE_MATCH_SPAN_START_END (1)
|
||||
#define MICROPY_PY_URE_SUB (0) // requires vstr interface
|
||||
#define MICROPY_PY_RE (1)
|
||||
#define MICROPY_PY_RE_MATCH_GROUPS (1)
|
||||
#define MICROPY_PY_RE_MATCH_SPAN_START_END (1)
|
||||
#define MICROPY_PY_RE_SUB (0) // requires vstr interface
|
||||
|
||||
#include <alloca.h>
|
||||
#include "py/dynruntime.h"
|
||||
@ -35,7 +35,7 @@ void *memmove(void *dest, const void *src, size_t n) {
|
||||
mp_obj_full_type_t match_type;
|
||||
mp_obj_full_type_t re_type;
|
||||
|
||||
#include "extmod/modure.c"
|
||||
#include "extmod/modre.c"
|
||||
|
||||
mp_map_elem_t match_locals_dict_table[5];
|
||||
STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table);
|
||||
@ -63,7 +63,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
|
||||
MP_OBJ_TYPE_SET_SLOT(&match_type, locals_dict, (void*)&match_locals_dict, 1);
|
||||
|
||||
re_type.base.type = (void*)&mp_fun_table.type_type;
|
||||
re_type.name = MP_QSTR_ure;
|
||||
re_type.name = MP_QSTR_re;
|
||||
MP_OBJ_TYPE_SET_SLOT(&re_type, print, re_print, 0);
|
||||
re_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_match), MP_OBJ_FROM_PTR(&re_match_obj) };
|
||||
re_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_search), MP_OBJ_FROM_PTR(&re_search_obj) };
|
@ -1,16 +0,0 @@
|
||||
#define MICROPY_PY_UHEAPQ (1)
|
||||
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
#include "extmod/moduheapq.c"
|
||||
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uheapq));
|
||||
mp_store_global(MP_QSTR_heappush, MP_OBJ_FROM_PTR(&mod_uheapq_heappush_obj));
|
||||
mp_store_global(MP_QSTR_heappop, MP_OBJ_FROM_PTR(&mod_uheapq_heappop_obj));
|
||||
mp_store_global(MP_QSTR_heapify, MP_OBJ_FROM_PTR(&mod_uheapq_heapify_obj));
|
||||
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
#define MICROPY_PY_URANDOM (1)
|
||||
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
|
||||
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
// Dynamic native modules don't support a data section so these must go in the BSS
|
||||
uint32_t yasmarang_pad, yasmarang_n, yasmarang_d;
|
||||
uint8_t yasmarang_dat;
|
||||
|
||||
#include "extmod/modurandom.c"
|
||||
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
yasmarang_pad = 0xeda4baba;
|
||||
yasmarang_n = 69;
|
||||
yasmarang_d = 233;
|
||||
|
||||
mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_urandom));
|
||||
mp_store_global(MP_QSTR_getrandbits, MP_OBJ_FROM_PTR(&mod_urandom_getrandbits_obj));
|
||||
mp_store_global(MP_QSTR_seed, MP_OBJ_FROM_PTR(&mod_urandom_seed_obj));
|
||||
#if MICROPY_PY_URANDOM_EXTRA_FUNCS
|
||||
mp_store_global(MP_QSTR_randrange, MP_OBJ_FROM_PTR(&mod_urandom_randrange_obj));
|
||||
mp_store_global(MP_QSTR_randint, MP_OBJ_FROM_PTR(&mod_urandom_randint_obj));
|
||||
mp_store_global(MP_QSTR_choice, MP_OBJ_FROM_PTR(&mod_urandom_choice_obj));
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_store_global(MP_QSTR_random, MP_OBJ_FROM_PTR(&mod_urandom_random_obj));
|
||||
mp_store_global(MP_QSTR_uniform, MP_OBJ_FROM_PTR(&mod_urandom_uniform_obj));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
#define MICROPY_PY_UZLIB (1)
|
||||
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
#if !defined(__linux__)
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
return mp_fun_table.memset_(s, c, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_obj_full_type_t decompio_type;
|
||||
|
||||
#include "extmod/moduzlib.c"
|
||||
|
||||
mp_map_elem_t decompio_locals_dict_table[3];
|
||||
STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
|
||||
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
decompio_type.base.type = mp_fun_table.type_type;
|
||||
decompio_type.name = MP_QSTR_DecompIO;
|
||||
MP_OBJ_TYPE_SET_SLOT(&decompio_type, make_new, &decompio_make_new, 0);
|
||||
MP_OBJ_TYPE_SET_SLOT(&decompio_type, protocol, &decompio_stream_p, 1);
|
||||
decompio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) };
|
||||
decompio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) };
|
||||
decompio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) };
|
||||
MP_OBJ_TYPE_SET_SLOT(&decompio_type, locals_dict, (void*)&decompio_locals_dict, 2);
|
||||
|
||||
mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uzlib));
|
||||
mp_store_global(MP_QSTR_decompress, MP_OBJ_FROM_PTR(&mod_uzlib_decompress_obj));
|
||||
mp_store_global(MP_QSTR_DecompIO, MP_OBJ_FROM_PTR(&decompio_type));
|
||||
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -68,7 +68,7 @@ MP_DEFINE_CONST_OBJ_TYPE(
|
||||
locals_dict, &example_Timer_locals_dict
|
||||
);
|
||||
|
||||
// Define all properties of the module.
|
||||
// Define all attributes of the module.
|
||||
// Table entries are key/value pairs of the attribute name (a string)
|
||||
// and the MicroPython object reference.
|
||||
// All identifiers and strings are written as MP_QSTR_xxx and will be
|
||||
|
@ -1,9 +1,8 @@
|
||||
EXAMPLE_MOD_DIR := $(USERMOD_DIR)
|
||||
CEXAMPLE_MOD_DIR := $(USERMOD_DIR)
|
||||
|
||||
# Add all C files to SRC_USERMOD.
|
||||
SRC_USERMOD += $(EXAMPLE_MOD_DIR)/examplemodule.c
|
||||
SRC_USERMOD += $(CEXAMPLE_MOD_DIR)/examplemodule.c
|
||||
|
||||
# We can add our module folder to include paths if needed
|
||||
# This is not actually needed in this example.
|
||||
CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR)
|
||||
CEXAMPLE_MOD_DIR := $(USERMOD_DIR)
|
||||
CFLAGS_USERMOD += -I$(CEXAMPLE_MOD_DIR)
|
||||
|
@ -4,7 +4,7 @@
|
||||
// See example.cpp for the definition.
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cppfunc_obj, cppfunc);
|
||||
|
||||
// Define all properties of the module.
|
||||
// Define all attributes of the module.
|
||||
// Table entries are key/value pairs of the attribute name (a string)
|
||||
// and the MicroPython object reference.
|
||||
// All identifiers and strings are written as MP_QSTR_xxx and will be
|
||||
|
1
examples/usercmodule/subpackage/README.md
Normal file
1
examples/usercmodule/subpackage/README.md
Normal file
@ -0,0 +1 @@
|
||||
This is an example of a user C module that includes subpackages.
|
19
examples/usercmodule/subpackage/micropython.cmake
Normal file
19
examples/usercmodule/subpackage/micropython.cmake
Normal file
@ -0,0 +1,19 @@
|
||||
# Create an INTERFACE library for our C module.
|
||||
add_library(usermod_subpackage_example INTERFACE)
|
||||
|
||||
# Add our source files to the lib
|
||||
target_sources(usermod_subpackage_example INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/examplemodule.c
|
||||
)
|
||||
|
||||
# Add the current directory as an include directory.
|
||||
target_include_directories(usermod_subpackage_example INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
target_compile_definitions(usermod_subpackage_example INTERFACE
|
||||
MICROPY_MODULE_BUILTIN_SUBPACKAGES=1
|
||||
)
|
||||
|
||||
# Link our INTERFACE library to the usermod target.
|
||||
target_link_libraries(usermod INTERFACE usermod_subpackage_example)
|
10
examples/usercmodule/subpackage/micropython.mk
Normal file
10
examples/usercmodule/subpackage/micropython.mk
Normal file
@ -0,0 +1,10 @@
|
||||
SUBPACKAGE_EXAMPLE_MOD_DIR := $(USERMOD_DIR)
|
||||
|
||||
# Add all C files to SRC_USERMOD.
|
||||
SRC_USERMOD += $(SUBPACKAGE_EXAMPLE_MOD_DIR)/modexamplepackage.c
|
||||
|
||||
# We can add our module folder to include paths if needed
|
||||
# This is not actually needed in this example.
|
||||
CFLAGS_USERMOD += -I$(SUBPACKAGE_EXAMPLE_MOD_DIR) -DMICROPY_MODULE_BUILTIN_SUBPACKAGES=1
|
||||
|
||||
QSTR_DEFS += $(SUBPACKAGE_EXAMPLE_MOD_DIR)/qstrdefsexamplepackage.h
|
84
examples/usercmodule/subpackage/modexamplepackage.c
Normal file
84
examples/usercmodule/subpackage/modexamplepackage.c
Normal file
@ -0,0 +1,84 @@
|
||||
// Include MicroPython API.
|
||||
#include "py/runtime.h"
|
||||
|
||||
// Define example_package.foo.bar.f()
|
||||
STATIC mp_obj_t example_package_foo_bar_f(void) {
|
||||
mp_printf(&mp_plat_print, "example_package.foo.bar.f\n");
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_foo_bar_f_obj, example_package_foo_bar_f);
|
||||
|
||||
// Define all attributes of the second-level sub-package (example_package.foo.bar).
|
||||
STATIC const mp_rom_map_elem_t example_package_foo_bar_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package_dot_foo_dot_bar) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_foo_bar_f_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(example_package_foo_bar_globals, example_package_foo_bar_globals_table);
|
||||
|
||||
// Define example_package.foo.bar module object.
|
||||
const mp_obj_module_t example_package_foo_bar_user_cmodule = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&example_package_foo_bar_globals,
|
||||
};
|
||||
|
||||
// Define example_package.foo.f()
|
||||
STATIC mp_obj_t example_package_foo_f(void) {
|
||||
mp_printf(&mp_plat_print, "example_package.foo.f\n");
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_foo_f_obj, example_package_foo_f);
|
||||
|
||||
// Define all attributes of the first-level sub-package (example_package.foo).
|
||||
STATIC const mp_rom_map_elem_t example_package_foo_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package_dot_foo) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_bar), MP_ROM_PTR(&example_package_foo_bar_user_cmodule) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_foo_f_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(example_package_foo_globals, example_package_foo_globals_table);
|
||||
|
||||
// Define example_package.foo module object.
|
||||
const mp_obj_module_t example_package_foo_user_cmodule = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&example_package_foo_globals,
|
||||
};
|
||||
|
||||
// Define example_package.f()
|
||||
STATIC mp_obj_t example_package_f(void) {
|
||||
mp_printf(&mp_plat_print, "example_package.f\n");
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_f_obj, example_package_f);
|
||||
|
||||
STATIC mp_obj_t example_package___init__(void) {
|
||||
if (!MP_STATE_VM(example_package_initialised)) {
|
||||
// __init__ for builtins is called each time the module is imported,
|
||||
// so ensure that initialisation only happens once.
|
||||
MP_STATE_VM(example_package_initialised) = true;
|
||||
mp_printf(&mp_plat_print, "example_package.__init__\n");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package___init___obj, example_package___init__);
|
||||
|
||||
// The "initialised" state is stored on mp_state so that it is cleared on soft
|
||||
// reset.
|
||||
MP_REGISTER_ROOT_POINTER(int example_package_initialised);
|
||||
|
||||
// Define all attributes of the top-level package (example_package).
|
||||
STATIC const mp_rom_map_elem_t example_package_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&example_package___init___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_foo), MP_ROM_PTR(&example_package_foo_user_cmodule) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_f_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(example_package_globals, example_package_globals_table);
|
||||
|
||||
// Define module object.
|
||||
const mp_obj_module_t example_package_user_cmodule = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&example_package_globals,
|
||||
};
|
||||
|
||||
// Register the module to make it available in Python.
|
||||
// Note: subpackages should not be registered with MP_REGISTER_MODULE.
|
||||
MP_REGISTER_MODULE(MP_QSTR_example_package, example_package_user_cmodule);
|
2
examples/usercmodule/subpackage/qstrdefsexamplepackage.h
Normal file
2
examples/usercmodule/subpackage/qstrdefsexamplepackage.h
Normal file
@ -0,0 +1,2 @@
|
||||
Q(example_package.foo)
|
||||
Q(example_package.foo.bar)
|
@ -1,20 +1,20 @@
|
||||
# This makefile fragment adds the source code files for the core extmod modules
|
||||
# and provides rules to build 3rd-party components for extmod modules.
|
||||
|
||||
# CIRCUITPY has removed many extmod modules.
|
||||
SRC_EXTMOD_C += \
|
||||
extmod/moduasyncio.c \
|
||||
extmod/modubinascii.c \
|
||||
extmod/modasyncio.c \
|
||||
extmod/modbinascii.c \
|
||||
extmod/modhashlib.c \
|
||||
extmod/modheapq.c \
|
||||
extmod/modjson.c \
|
||||
extmod/modos.c \
|
||||
extmod/modplatform.c\
|
||||
extmod/modrandom.c \
|
||||
extmod/modre.c \
|
||||
extmod/modselect.c \
|
||||
extmod/moductypes.c \
|
||||
extmod/moduhashlib.c \
|
||||
extmod/moduheapq.c \
|
||||
extmod/modujson.c \
|
||||
extmod/moduos.c \
|
||||
extmod/moduplatform.c\
|
||||
extmod/modurandom.c \
|
||||
extmod/modure.c \
|
||||
extmod/moduselect.c \
|
||||
extmod/moduzlib.c \
|
||||
extmod/utime_mphal.c \
|
||||
extmod/modzlib.c \
|
||||
extmod/vfs.c \
|
||||
extmod/vfs_blockdev.c \
|
||||
extmod/vfs_fat.c \
|
||||
@ -81,10 +81,9 @@ endif
|
||||
################################################################################
|
||||
# ussl
|
||||
|
||||
ifeq ($(MICROPY_PY_USSL),1)
|
||||
CFLAGS_EXTMOD += -DMICROPY_PY_USSL=1
|
||||
ifeq ($(MICROPY_PY_SSL),1)
|
||||
CFLAGS_EXTMOD += -DMICROPY_PY_SSL=1
|
||||
ifeq ($(MICROPY_SSL_AXTLS),1)
|
||||
CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include
|
||||
AXTLS_DIR = lib/axtls
|
||||
GIT_SUBMODULES += $(AXTLS_DIR)
|
||||
CFLAGS_EXTMOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include
|
||||
@ -146,7 +145,6 @@ SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\
|
||||
md4.c \
|
||||
md5.c \
|
||||
md.c \
|
||||
md_wrap.c \
|
||||
oid.c \
|
||||
padlock.c \
|
||||
pem.c \
|
||||
@ -171,9 +169,11 @@ SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\
|
||||
ssl_cli.c \
|
||||
ssl_cookie.c \
|
||||
ssl_srv.c \
|
||||
ssl_msg.c \
|
||||
ssl_ticket.c \
|
||||
ssl_tls.c \
|
||||
timing.c \
|
||||
constant_time.c \
|
||||
x509.c \
|
||||
x509_create.c \
|
||||
x509_crl.c \
|
||||
@ -267,7 +267,7 @@ SRC_THIRDPARTY_C += $(addprefix $(BTREE_DIR)/,\
|
||||
CFLAGS_EXTMOD += -DMICROPY_PY_BTREE=1
|
||||
# we need to suppress certain warnings to get berkeley-db to compile cleanly
|
||||
# and we have separate BTREE_DEFS so the definitions don't interfere with other source code
|
||||
$(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS)
|
||||
$(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter -Wno-deprecated-non-prototype -Wno-unknown-warning-option $(BTREE_DEFS)
|
||||
$(BUILD)/extmod/modbtree.o: CFLAGS += $(BTREE_DEFS)
|
||||
endif
|
||||
|
||||
@ -311,8 +311,51 @@ SRC_THIRDPARTY_C += $(addprefix $(WIZNET5K_DIR)/,\
|
||||
Internet/DHCP/dhcp.c \
|
||||
)
|
||||
endif
|
||||
endif # MICROPY_PY_NETWORK_WIZNET5K
|
||||
|
||||
ifeq ($(MICROPY_PY_NETWORK_ESP_HOSTED),1)
|
||||
ESP_HOSTED_DIR = drivers/esp-hosted
|
||||
PROTOBUF_C_DIR = lib/protobuf-c
|
||||
PROTOC ?= protoc-c
|
||||
GIT_SUBMODULES += $(PROTOBUF_C_DIR)
|
||||
|
||||
CFLAGS += -DMICROPY_PY_NETWORK_ESP_HOSTED=1
|
||||
CFLAGS_EXTMOD += -DMICROPY_PY_NETWORK_ESP_HOSTED=1
|
||||
INC += -I$(TOP)/$(ESP_HOSTED_DIR)
|
||||
|
||||
ESP_HOSTED_SRC_C = $(addprefix $(ESP_HOSTED_DIR)/,\
|
||||
esp_hosted_wifi.c \
|
||||
esp_hosted_netif.c \
|
||||
esp_hosted_hal.c \
|
||||
)
|
||||
|
||||
ifeq ($(MICROPY_PY_BLUETOOTH),1)
|
||||
ESP_HOSTED_SRC_C += $(ESP_HOSTED_DIR)/esp_hosted_bthci.c
|
||||
endif
|
||||
|
||||
# Include the protobuf-c support functions
|
||||
ESP_HOSTED_SRC_C += $(addprefix $(PROTOBUF_C_DIR)/,\
|
||||
protobuf-c/protobuf-c.c \
|
||||
)
|
||||
|
||||
$(BUILD)/$(PROTOBUF_C_DIR)/%.o: CFLAGS += -Wno-unused-but-set-variable
|
||||
|
||||
# Generate esp_hosted-pb-c.c|h from esp_hosted.proto
|
||||
PROTO_GEN_SRC = $(BUILD)/extmod/esp_hosted.pb-c.c
|
||||
ESP_HOSTED_SRC_C += $(PROTO_GEN_SRC)
|
||||
|
||||
$(PROTO_GEN_SRC): $(TOP)/$(ESP_HOSTED_DIR)/esp_hosted.proto
|
||||
$(PROTOC) --proto_path=$(dir $<) --c_out=$(dir $@) $<
|
||||
|
||||
# Scope the protobuf include paths to the esp_hosted source files, only
|
||||
ESP_HOSTED_OBJS = $(addprefix $(BUILD)/, $(ESP_HOSTED_SRC_C:.c=.o))
|
||||
$(ESP_HOSTED_OBJS): $(PROTO_GEN_SRC)
|
||||
$(ESP_HOSTED_OBJS): CFLAGS += -I$(dir $(PROTO_GEN_SRC)) -I$(TOP)/$(PROTOBUF_C_DIR)
|
||||
|
||||
DRIVERS_SRC_C += $(ESP_HOSTED_SRC_C)
|
||||
|
||||
endif # MICROPY_PY_NETWORK_ESP_HOSTED
|
||||
|
||||
################################################################################
|
||||
# bluetooth
|
||||
|
||||
|
@ -32,17 +32,17 @@
|
||||
#include <stddef.h>
|
||||
#include "py/runtime.h"
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_os_dupterm_obj);
|
||||
|
||||
#if MICROPY_PY_OS_DUPTERM
|
||||
bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream);
|
||||
void mp_uos_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached);
|
||||
uintptr_t mp_uos_dupterm_poll(uintptr_t poll_flags);
|
||||
int mp_uos_dupterm_rx_chr(void);
|
||||
void mp_uos_dupterm_tx_strn(const char *str, size_t len);
|
||||
void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc);
|
||||
bool mp_os_dupterm_is_builtin_stream(mp_const_obj_t stream);
|
||||
void mp_os_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached);
|
||||
uintptr_t mp_os_dupterm_poll(uintptr_t poll_flags);
|
||||
int mp_os_dupterm_rx_chr(void);
|
||||
void mp_os_dupterm_tx_strn(const char *str, size_t len);
|
||||
void mp_os_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc);
|
||||
#else
|
||||
#define mp_uos_dupterm_tx_strn(s, l)
|
||||
#define mp_os_dupterm_tx_strn(s, l)
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MISC_H
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "py/pairheap.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
#if MICROPY_PY_UASYNCIO
|
||||
#if MICROPY_PY_ASYNCIO
|
||||
|
||||
#if CIRCUITPY && !(defined(__unix__) || defined(__APPLE__))
|
||||
#include "shared-bindings/supervisor/__init__.h"
|
||||
@ -68,14 +68,14 @@ STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, si
|
||||
// Ticks for task ordering in pairing heap
|
||||
|
||||
STATIC mp_obj_t ticks(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_TIME_TICKS_PERIOD - 1));
|
||||
}
|
||||
|
||||
STATIC mp_int_t ticks_diff(mp_obj_t t1_in, mp_obj_t t0_in) {
|
||||
mp_uint_t t0 = MP_OBJ_SMALL_INT_VALUE(t0_in);
|
||||
mp_uint_t t1 = MP_OBJ_SMALL_INT_VALUE(t1_in);
|
||||
mp_int_t diff = ((t1 - t0 + MICROPY_PY_UTIME_TICKS_PERIOD / 2) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1))
|
||||
- MICROPY_PY_UTIME_TICKS_PERIOD / 2;
|
||||
mp_int_t diff = ((t1 - t0 + MICROPY_PY_TIME_TICKS_PERIOD / 2) & (MICROPY_PY_TIME_TICKS_PERIOD - 1))
|
||||
- MICROPY_PY_TIME_TICKS_PERIOD / 2;
|
||||
return diff;
|
||||
}
|
||||
|
||||
@ -145,11 +145,6 @@ STATIC const mp_rom_map_elem_t task_queue_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&task_queue_push_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&task_queue_pop_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&task_queue_remove_obj) },
|
||||
|
||||
// CIRCUITPYTHON: Remove these in CircuitPython 10.0.0
|
||||
{ MP_ROM_QSTR(MP_QSTR_push_head), MP_ROM_PTR(&task_queue_push_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_push_sorted), MP_ROM_PTR(&task_queue_push_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pop_head), MP_ROM_PTR(&task_queue_pop_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(task_queue_locals_dict, task_queue_locals_dict_table);
|
||||
|
||||
@ -164,8 +159,8 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
/******************************************************************************/
|
||||
// Task class
|
||||
|
||||
// This is the core uasyncio context with cur_task, _task_queue and CancelledError.
|
||||
STATIC mp_obj_t uasyncio_context = MP_OBJ_NULL;
|
||||
// This is the core asyncio context with cur_task, _task_queue and CancelledError.
|
||||
STATIC mp_obj_t asyncio_context = MP_OBJ_NULL;
|
||||
|
||||
STATIC mp_obj_t task_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, 2, false);
|
||||
@ -177,7 +172,7 @@ STATIC mp_obj_t task_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
|
||||
self->state = TASK_STATE_RUNNING_NOT_WAITED_ON;
|
||||
self->ph_key = MP_OBJ_NEW_SMALL_INT(0);
|
||||
if (n_args == 2) {
|
||||
uasyncio_context = args[1];
|
||||
asyncio_context = args[1];
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
@ -195,7 +190,7 @@ STATIC mp_obj_t task_cancel(mp_obj_t self_in) {
|
||||
return mp_const_false;
|
||||
}
|
||||
// Can't cancel self (not supported yet).
|
||||
mp_obj_t cur_task = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task));
|
||||
mp_obj_t cur_task = mp_obj_dict_get(asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task));
|
||||
if (self_in == cur_task) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("can't cancel self"));
|
||||
}
|
||||
@ -204,7 +199,7 @@ STATIC mp_obj_t task_cancel(mp_obj_t self_in) {
|
||||
self = MP_OBJ_TO_PTR(self->data);
|
||||
}
|
||||
|
||||
mp_obj_t _task_queue = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR__task_queue));
|
||||
mp_obj_t _task_queue = mp_obj_dict_get(asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR__task_queue));
|
||||
|
||||
// Reschedule Task as a cancelled task.
|
||||
mp_obj_t dest[3];
|
||||
@ -227,7 +222,7 @@ STATIC mp_obj_t task_cancel(mp_obj_t self_in) {
|
||||
task_queue_push(2, dest);
|
||||
}
|
||||
|
||||
self->data = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_CancelledError));
|
||||
self->data = mp_obj_dict_get(asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_CancelledError));
|
||||
|
||||
return mp_const_true;
|
||||
}
|
||||
@ -303,7 +298,7 @@ STATIC mp_obj_t task_iternext(mp_obj_t self_in) {
|
||||
}
|
||||
} else {
|
||||
// Put calling task on waiting queue.
|
||||
mp_obj_t cur_task = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task));
|
||||
mp_obj_t cur_task = mp_obj_dict_get(asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task));
|
||||
mp_obj_t args[2] = { self->state, cur_task };
|
||||
task_queue_push(2, args);
|
||||
// Set calling task's data to this task that it waits on, to double-link it.
|
||||
@ -327,20 +322,20 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
);
|
||||
|
||||
/******************************************************************************/
|
||||
// C-level uasyncio module
|
||||
// C-level asyncio module
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_uasyncio_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__uasyncio) },
|
||||
STATIC const mp_rom_map_elem_t mp_module_asyncio_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__asyncio) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_TaskQueue), MP_ROM_PTR(&task_queue_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Task), MP_ROM_PTR(&task_type) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_uasyncio_globals, mp_module_uasyncio_globals_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_asyncio_globals, mp_module_asyncio_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uasyncio = {
|
||||
const mp_obj_module_t mp_module_asyncio = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_uasyncio_globals,
|
||||
.globals = (mp_obj_dict_t *)&mp_module_asyncio_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR__asyncio, mp_module_uasyncio);
|
||||
MP_REGISTER_MODULE(MP_QSTR__asyncio, mp_module_asyncio);
|
||||
|
||||
#endif // MICROPY_PY_UASYNCIO
|
||||
#endif // MICROPY_PY_ASYNCIO
|
@ -34,7 +34,7 @@
|
||||
|
||||
#include "lib/uzlib/tinf.h"
|
||||
|
||||
#if MICROPY_PY_UBINASCII
|
||||
#if MICROPY_PY_BINASCII
|
||||
|
||||
static void check_not_unicode(const mp_obj_t arg) {
|
||||
#if MICROPY_CPYTHON_COMPAT
|
||||
@ -48,7 +48,6 @@ static void check_not_unicode(const mp_obj_t arg) {
|
||||
STATIC mp_obj_t bytes_hex_as_bytes(size_t n_args, const mp_obj_t *args) {
|
||||
return mp_obj_bytes_hex(n_args, args, &mp_type_bytes);
|
||||
}
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_hex_as_bytes_obj, 1, 2, bytes_hex_as_bytes);
|
||||
|
||||
STATIC mp_obj_t bytes_fromhex_bytes(mp_obj_t data) {
|
||||
@ -82,7 +81,7 @@ STATIC mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) {
|
||||
byte *in = bufinfo.buf;
|
||||
|
||||
vstr_t vstr;
|
||||
vstr_init(&vstr, (bufinfo.len / 4) * 3 + 1); // Potentially over-allocate
|
||||
vstr_init(&vstr, (bufinfo.len * 3) / 4 + 1); // Potentially over-allocate
|
||||
byte *out = (byte *)vstr.buf;
|
||||
|
||||
uint shift = 0;
|
||||
@ -220,6 +219,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_binascii_b2a_base64_obj, 1, mod_binascii_b
|
||||
*/
|
||||
|
||||
#if MICROPY_PY_UBINASCII_CRC32
|
||||
#include "lib/uzlib/tinf.h"
|
||||
|
||||
STATIC mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
// CIRCUITPY
|
||||
@ -233,14 +234,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_bin
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubinascii) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_binascii) },
|
||||
#if MICROPY_PY_BUILTINS_BYTES_HEX
|
||||
{ MP_ROM_QSTR(MP_QSTR_hexlify), MP_ROM_PTR(&bytes_hex_as_bytes_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&bytes_fromhex_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_a2b_base64), MP_ROM_PTR(&mod_binascii_a2b_base64_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_b2a_base64), MP_ROM_PTR(&mod_binascii_b2a_base64_obj) },
|
||||
#if MICROPY_PY_UBINASCII_CRC32
|
||||
#if MICROPY_PY_BINASCII_CRC32
|
||||
{ MP_ROM_QSTR(MP_QSTR_crc32), MP_ROM_PTR(&mod_binascii_crc32_obj) },
|
||||
#endif
|
||||
};
|
||||
@ -252,6 +253,6 @@ const mp_obj_module_t mp_module_ubinascii = {
|
||||
.globals = (mp_obj_dict_t *)&mp_module_binascii_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_binascii, mp_module_ubinascii);
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_binascii, mp_module_binascii);
|
||||
|
||||
#endif // MICROPY_PY_UBINASCII
|
||||
#endif // MICROPY_PY_BINASCII
|
415
extmod/moddeflate.c
Normal file
415
extmod/moddeflate.c
Normal file
@ -0,0 +1,415 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Jim Mussared
|
||||
*
|
||||
* Based on extmod/modzlib.c
|
||||
* Copyright (c) 2014-2016 Paul Sokolovsky
|
||||
* Copyright (c) 2021-2023 Damien P. George
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/mperrno.h"
|
||||
|
||||
#if MICROPY_PY_DEFLATE
|
||||
|
||||
#include "lib/uzlib/uzlib.h"
|
||||
|
||||
#if 0 // print debugging info
|
||||
#define DEBUG_printf DEBUG_printf
|
||||
#else // don't print debugging info
|
||||
#define DEBUG_printf(...) (void)0
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
DEFLATEIO_FORMAT_MIN = 0,
|
||||
DEFLATEIO_FORMAT_AUTO = DEFLATEIO_FORMAT_MIN, // Read mode this means auto-detect zlib/gzip, write mode this means RAW.
|
||||
DEFLATEIO_FORMAT_RAW = 1,
|
||||
DEFLATEIO_FORMAT_ZLIB = 2,
|
||||
DEFLATEIO_FORMAT_GZIP = 3,
|
||||
DEFLATEIO_FORMAT_MAX = DEFLATEIO_FORMAT_GZIP,
|
||||
} deflateio_format_t;
|
||||
|
||||
// This is used when the wbits is unset in the DeflateIO constructor. Default
|
||||
// to the smallest window size (faster compression, less RAM usage, etc).
|
||||
const int DEFLATEIO_DEFAULT_WBITS = 8;
|
||||
|
||||
typedef struct {
|
||||
void *window;
|
||||
uzlib_uncomp_t decomp;
|
||||
bool eof;
|
||||
} mp_obj_deflateio_read_t;
|
||||
|
||||
#if MICROPY_PY_DEFLATE_COMPRESS
|
||||
typedef struct {
|
||||
void *window;
|
||||
size_t input_len;
|
||||
uint32_t input_checksum;
|
||||
uzlib_lz77_state_t lz77;
|
||||
} mp_obj_deflateio_write_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t stream;
|
||||
uint8_t format : 2;
|
||||
uint8_t window_bits : 4;
|
||||
bool close : 1;
|
||||
mp_obj_deflateio_read_t *read;
|
||||
#if MICROPY_PY_DEFLATE_COMPRESS
|
||||
mp_obj_deflateio_write_t *write;
|
||||
#endif
|
||||
} mp_obj_deflateio_t;
|
||||
|
||||
STATIC int deflateio_read_stream(void *data) {
|
||||
mp_obj_deflateio_t *self = data;
|
||||
const mp_stream_p_t *stream = mp_get_stream(self->stream);
|
||||
int err;
|
||||
byte c;
|
||||
mp_uint_t out_sz = stream->read(self->stream, &c, 1, &err);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
mp_raise_OSError(err);
|
||||
}
|
||||
if (out_sz == 0) {
|
||||
mp_raise_type(&mp_type_EOFError);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
STATIC bool deflateio_init_read(mp_obj_deflateio_t *self) {
|
||||
if (self->read) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mp_get_stream_raise(self->stream, MP_STREAM_OP_READ);
|
||||
|
||||
self->read = m_new_obj(mp_obj_deflateio_read_t);
|
||||
memset(&self->read->decomp, 0, sizeof(self->read->decomp));
|
||||
self->read->decomp.source_read_data = self;
|
||||
self->read->decomp.source_read_cb = deflateio_read_stream;
|
||||
self->read->eof = false;
|
||||
|
||||
// Don't modify self->window_bits as it may also be used for write.
|
||||
int wbits = self->window_bits;
|
||||
|
||||
if (self->format == DEFLATEIO_FORMAT_RAW) {
|
||||
if (wbits == 0) {
|
||||
// The docs recommends always setting wbits explicitly when using
|
||||
// RAW, but we still allow a default.
|
||||
wbits = DEFLATEIO_DEFAULT_WBITS;
|
||||
}
|
||||
} else {
|
||||
// Parse the header if we're in NONE/ZLIB/GZIP modes.
|
||||
int header_wbits;
|
||||
int header_type = uzlib_parse_zlib_gzip_header(&self->read->decomp, &header_wbits);
|
||||
if (header_type < 0) {
|
||||
// Stream header was invalid.
|
||||
return false;
|
||||
}
|
||||
if ((self->format == DEFLATEIO_FORMAT_ZLIB && header_type != UZLIB_HEADER_ZLIB) || (self->format == DEFLATEIO_FORMAT_GZIP && header_type != UZLIB_HEADER_GZIP)) {
|
||||
// Not what we expected.
|
||||
return false;
|
||||
}
|
||||
// header_wbits will either be 15 (gzip) or 8-15 (zlib).
|
||||
if (wbits == 0 || header_wbits < wbits) {
|
||||
// If the header specified something lower, then use that instead.
|
||||
// No point doing a bigger allocation than we need to.
|
||||
wbits = header_wbits;
|
||||
}
|
||||
}
|
||||
|
||||
size_t window_len = 1 << wbits;
|
||||
self->read->window = m_new(uint8_t, window_len);
|
||||
|
||||
uzlib_uncompress_init(&self->read->decomp, self->read->window, window_len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if MICROPY_PY_DEFLATE_COMPRESS
|
||||
STATIC void deflateio_out_byte(void *data, uint8_t b) {
|
||||
mp_obj_deflateio_t *self = data;
|
||||
const mp_stream_p_t *stream = mp_get_stream(self->stream);
|
||||
int err;
|
||||
mp_uint_t ret = stream->write(self->stream, &b, 1, &err);
|
||||
if (ret == MP_STREAM_ERROR) {
|
||||
mp_raise_OSError(err);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC bool deflateio_init_write(mp_obj_deflateio_t *self) {
|
||||
if (self->write) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const mp_stream_p_t *stream = mp_get_stream_raise(self->stream, MP_STREAM_OP_WRITE);
|
||||
|
||||
self->write = m_new_obj(mp_obj_deflateio_write_t);
|
||||
self->write->input_len = 0;
|
||||
|
||||
int wbits = self->window_bits;
|
||||
if (wbits == 0) {
|
||||
// Same default wbits for all formats.
|
||||
wbits = DEFLATEIO_DEFAULT_WBITS;
|
||||
}
|
||||
size_t window_len = 1 << wbits;
|
||||
self->write->window = m_new(uint8_t, window_len);
|
||||
|
||||
uzlib_lz77_init(&self->write->lz77, self->write->window, window_len);
|
||||
self->write->lz77.dest_write_data = self;
|
||||
self->write->lz77.dest_write_cb = deflateio_out_byte;
|
||||
|
||||
// Write header if needed.
|
||||
mp_uint_t ret = 0;
|
||||
int err;
|
||||
if (self->format == DEFLATEIO_FORMAT_ZLIB) {
|
||||
// -----CMF------ ----------FLG---------------
|
||||
// CINFO(5) CM(3) FLEVEL(2) FDICT(1) FCHECK(5)
|
||||
uint8_t buf[] = { 0x08, 0x80 }; // CM=2 (deflate), FLEVEL=2 (default), FDICT=0 (no dictionary)
|
||||
buf[0] |= MAX(wbits - 8, 1) << 4; // base-2 logarithm of the LZ77 window size, minus eight.
|
||||
buf[1] |= 31 - ((buf[0] * 256 + buf[1]) % 31); // (CMF*256 + FLG) % 31 == 0.
|
||||
ret = stream->write(self->stream, buf, sizeof(buf), &err);
|
||||
|
||||
self->write->input_checksum = 1; // ADLER32
|
||||
} else if (self->format == DEFLATEIO_FORMAT_GZIP) {
|
||||
// ID1(8) ID2(8) CM(8) ---FLG--- MTIME(32) XFL(8) OS(8)
|
||||
// FLG: x x x FCOMMENT FNAME FEXTRA FHCRC FTEXT
|
||||
uint8_t buf[] = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03 }; // MTIME=0, XFL=4 (fastest), OS=3 (unix)
|
||||
ret = stream->write(self->stream, buf, sizeof(buf), &err);
|
||||
|
||||
self->write->input_checksum = ~0; // CRC32
|
||||
}
|
||||
if (ret == MP_STREAM_ERROR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write starting block.
|
||||
uzlib_start_block(&self->write->lz77);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t deflateio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) {
|
||||
// args: stream, format=NONE, wbits=0, close=False
|
||||
mp_arg_check_num(n_args, n_kw, 1, 4, false);
|
||||
|
||||
mp_int_t format = n_args > 1 ? mp_obj_get_int(args_in[1]) : DEFLATEIO_FORMAT_AUTO;
|
||||
mp_int_t wbits = n_args > 2 ? mp_obj_get_int(args_in[2]) : 0;
|
||||
|
||||
if (format < DEFLATEIO_FORMAT_MIN || format > DEFLATEIO_FORMAT_MAX) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("format"));
|
||||
}
|
||||
if (wbits != 0 && (wbits < 5 || wbits > 15)) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("wbits"));
|
||||
}
|
||||
|
||||
mp_obj_deflateio_t *self = mp_obj_malloc(mp_obj_deflateio_t, type);
|
||||
self->stream = args_in[0];
|
||||
self->format = format;
|
||||
self->window_bits = wbits;
|
||||
self->read = NULL;
|
||||
#if MICROPY_PY_DEFLATE_COMPRESS
|
||||
self->write = NULL;
|
||||
#endif
|
||||
self->close = n_args > 3 ? mp_obj_is_true(args_in[3]) : false;
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t deflateio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_deflateio_t *self = MP_OBJ_TO_PTR(o_in);
|
||||
|
||||
if (self->stream == MP_OBJ_NULL || !deflateio_init_read(self)) {
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
if (self->read->eof) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
self->read->decomp.dest = buf;
|
||||
self->read->decomp.dest_limit = (uint8_t *)buf + size;
|
||||
int st = uzlib_uncompress_chksum(&self->read->decomp);
|
||||
if (st == UZLIB_DONE) {
|
||||
self->read->eof = true;
|
||||
}
|
||||
if (st < 0) {
|
||||
DEBUG_printf("uncompress error=" INT_FMT "\n", st);
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
return self->read->decomp.dest - (uint8_t *)buf;
|
||||
}
|
||||
|
||||
#if MICROPY_PY_DEFLATE_COMPRESS
|
||||
STATIC mp_uint_t deflateio_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_deflateio_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
if (self->stream == MP_OBJ_NULL || !deflateio_init_write(self)) {
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
self->write->input_len += size;
|
||||
if (self->format == DEFLATEIO_FORMAT_ZLIB) {
|
||||
self->write->input_checksum = uzlib_adler32(buf, size, self->write->input_checksum);
|
||||
} else if (self->format == DEFLATEIO_FORMAT_GZIP) {
|
||||
self->write->input_checksum = uzlib_crc32(buf, size, self->write->input_checksum);
|
||||
}
|
||||
|
||||
uzlib_lz77_compress(&self->write->lz77, buf, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static inline void put_le32(char *buf, uint32_t value) {
|
||||
buf[0] = value & 0xff;
|
||||
buf[1] = value >> 8 & 0xff;
|
||||
buf[2] = value >> 16 & 0xff;
|
||||
buf[3] = value >> 24 & 0xff;
|
||||
}
|
||||
|
||||
static inline void put_be32(char *buf, uint32_t value) {
|
||||
buf[3] = value & 0xff;
|
||||
buf[2] = value >> 8 & 0xff;
|
||||
buf[1] = value >> 16 & 0xff;
|
||||
buf[0] = value >> 24 & 0xff;
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC mp_uint_t deflateio_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
if (request == MP_STREAM_CLOSE) {
|
||||
mp_obj_deflateio_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
mp_uint_t ret = 0;
|
||||
|
||||
if (self->stream != MP_OBJ_NULL) {
|
||||
#if MICROPY_PY_DEFLATE_COMPRESS
|
||||
if (self->write) {
|
||||
uzlib_finish_block(&self->write->lz77);
|
||||
|
||||
const mp_stream_p_t *stream = mp_get_stream(self->stream);
|
||||
|
||||
// Write footer if needed.
|
||||
if (self->format == DEFLATEIO_FORMAT_ZLIB || self->format == DEFLATEIO_FORMAT_GZIP) {
|
||||
char footer[8];
|
||||
size_t footer_len;
|
||||
if (self->format == DEFLATEIO_FORMAT_ZLIB) {
|
||||
put_be32(&footer[0], self->write->input_checksum);
|
||||
footer_len = 4;
|
||||
} else { // DEFLATEIO_FORMAT_GZIP
|
||||
put_le32(&footer[0], ~self->write->input_checksum);
|
||||
put_le32(&footer[4], self->write->input_len);
|
||||
footer_len = 8;
|
||||
}
|
||||
if (stream->write(self->stream, footer, footer_len, errcode) == MP_STREAM_ERROR) {
|
||||
ret = MP_STREAM_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Only close the stream if required. e.g. when using io.BytesIO
|
||||
// it needs to stay open so that getvalue() can be called.
|
||||
if (self->close) {
|
||||
mp_stream_close(self->stream);
|
||||
}
|
||||
|
||||
// Either way, free the reference to the stream.
|
||||
self->stream = MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC const mp_stream_p_t deflateio_stream_p = {
|
||||
.read = deflateio_read,
|
||||
#if MICROPY_PY_DEFLATE_COMPRESS
|
||||
.write = deflateio_write,
|
||||
#endif
|
||||
.ioctl = deflateio_ioctl,
|
||||
};
|
||||
|
||||
#if !MICROPY_ENABLE_DYNRUNTIME
|
||||
STATIC const mp_rom_map_elem_t deflateio_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
|
||||
#if MICROPY_PY_DEFLATE_COMPRESS
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&mp_stream___exit___obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(deflateio_locals_dict, deflateio_locals_dict_table);
|
||||
|
||||
STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
deflateio_type,
|
||||
MP_QSTR_DeflateIO,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, deflateio_make_new,
|
||||
protocol, &deflateio_stream_p,
|
||||
locals_dict, &deflateio_locals_dict
|
||||
);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_deflate_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_deflate) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DeflateIO), MP_ROM_PTR(&deflateio_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_AUTO), MP_ROM_INT(DEFLATEIO_FORMAT_AUTO) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RAW), MP_ROM_INT(DEFLATEIO_FORMAT_RAW) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ZLIB), MP_ROM_INT(DEFLATEIO_FORMAT_ZLIB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GZIP), MP_ROM_INT(DEFLATEIO_FORMAT_GZIP) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_deflate_globals, mp_module_deflate_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_deflate = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_deflate_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_deflate, mp_module_deflate);
|
||||
#endif // !MICROPY_ENABLE_DYNRUNTIME
|
||||
|
||||
// Source files #include'd here to make sure they're compiled in
|
||||
// only if the module is enabled.
|
||||
|
||||
#include "lib/uzlib/tinflate.c"
|
||||
#include "lib/uzlib/header.c"
|
||||
#include "lib/uzlib/adler32.c"
|
||||
#include "lib/uzlib/crc32.c"
|
||||
|
||||
#if MICROPY_PY_DEFLATE_COMPRESS
|
||||
#include "lib/uzlib/lz77.c"
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_PY_DEFLATE
|
@ -29,13 +29,13 @@
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if MICROPY_PY_UHASHLIB
|
||||
#if MICROPY_PY_HASHLIB
|
||||
|
||||
#if MICROPY_SSL_MBEDTLS
|
||||
#include "mbedtls/version.h"
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UHASHLIB_SHA256
|
||||
#if MICROPY_PY_HASHLIB_SHA256
|
||||
|
||||
#if MICROPY_SSL_MBEDTLS
|
||||
#include "mbedtls/sha256.h"
|
||||
@ -45,7 +45,7 @@
|
||||
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UHASHLIB_SHA1 || MICROPY_PY_UHASHLIB_MD5
|
||||
#if MICROPY_PY_HASHLIB_SHA1 || MICROPY_PY_HASHLIB_MD5
|
||||
|
||||
#if MICROPY_SSL_AXTLS
|
||||
#include "lib/axtls/crypto/crypto.h"
|
||||
@ -64,47 +64,47 @@ typedef struct _mp_obj_hash_t {
|
||||
uintptr_t state[0]; // must be aligned to a machine word
|
||||
} mp_obj_hash_t;
|
||||
|
||||
static void uhashlib_ensure_not_final(mp_obj_hash_t *self) {
|
||||
static void hashlib_ensure_not_final(mp_obj_hash_t *self) {
|
||||
if (self->final) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("hash is final"));
|
||||
}
|
||||
}
|
||||
|
||||
#if MICROPY_PY_UHASHLIB_SHA256
|
||||
STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg);
|
||||
#if MICROPY_PY_HASHLIB_SHA256
|
||||
STATIC mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg);
|
||||
|
||||
#if MICROPY_SSL_MBEDTLS
|
||||
|
||||
#if MBEDTLS_VERSION_NUMBER < 0x02070000
|
||||
#if MBEDTLS_VERSION_NUMBER < 0x02070000 || MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
#define mbedtls_sha256_starts_ret mbedtls_sha256_starts
|
||||
#define mbedtls_sha256_update_ret mbedtls_sha256_update
|
||||
#define mbedtls_sha256_finish_ret mbedtls_sha256_finish
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t hashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_sha256_context), type);
|
||||
o->final = false;
|
||||
mbedtls_sha256_init((mbedtls_sha256_context *)&o->state);
|
||||
mbedtls_sha256_starts_ret((mbedtls_sha256_context *)&o->state, 0);
|
||||
if (n_args == 1) {
|
||||
uhashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
hashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
STATIC mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uhashlib_ensure_not_final(self);
|
||||
hashlib_ensure_not_final(self);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
|
||||
mbedtls_sha256_update_ret((mbedtls_sha256_context *)&self->state, bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
|
||||
STATIC mp_obj_t hashlib_sha256_digest(mp_obj_t self_in) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uhashlib_ensure_not_final(self);
|
||||
hashlib_ensure_not_final(self);
|
||||
self->final = true;
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, 32);
|
||||
@ -124,30 +124,29 @@ static void check_not_unicode(const mp_obj_t arg) {
|
||||
|
||||
#include "lib/crypto-algorithms/sha256.c"
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t hashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(CRYAL_SHA256_CTX), type);
|
||||
o->final = false;
|
||||
sha256_init((CRYAL_SHA256_CTX *)o->state);
|
||||
if (n_args == 1) {
|
||||
uhashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
hashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
check_not_unicode(arg);
|
||||
STATIC mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uhashlib_ensure_not_final(self);
|
||||
hashlib_ensure_not_final(self);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
|
||||
sha256_update((CRYAL_SHA256_CTX *)self->state, bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
|
||||
STATIC mp_obj_t hashlib_sha256_digest(mp_obj_t self_in) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uhashlib_ensure_not_final(self);
|
||||
hashlib_ensure_not_final(self);
|
||||
self->final = true;
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, SHA256_BLOCK_SIZE);
|
||||
@ -156,52 +155,52 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(uhashlib_sha256_update_obj, uhashlib_sha256_update);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(uhashlib_sha256_digest_obj, uhashlib_sha256_digest);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(hashlib_sha256_update_obj, hashlib_sha256_update);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(hashlib_sha256_digest_obj, hashlib_sha256_digest);
|
||||
|
||||
STATIC const mp_rom_map_elem_t uhashlib_sha256_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&uhashlib_sha256_update_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&uhashlib_sha256_digest_obj) },
|
||||
STATIC const mp_rom_map_elem_t hashlib_sha256_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&hashlib_sha256_update_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&hashlib_sha256_digest_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(uhashlib_sha256_locals_dict, uhashlib_sha256_locals_dict_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(hashlib_sha256_locals_dict, hashlib_sha256_locals_dict_table);
|
||||
|
||||
STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
uhashlib_sha256_type,
|
||||
hashlib_sha256_type,
|
||||
MP_QSTR_sha256,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, uhashlib_sha256_make_new,
|
||||
locals_dict, &uhashlib_sha256_locals_dict
|
||||
make_new, hashlib_sha256_make_new,
|
||||
locals_dict, &hashlib_sha256_locals_dict
|
||||
);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UHASHLIB_SHA1
|
||||
STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg);
|
||||
#if MICROPY_PY_HASHLIB_SHA1
|
||||
STATIC mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg);
|
||||
|
||||
#if MICROPY_SSL_AXTLS
|
||||
STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t hashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(SHA1_CTX), type);
|
||||
o->final = false;
|
||||
SHA1_Init((SHA1_CTX *)o->state);
|
||||
if (n_args == 1) {
|
||||
uhashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
hashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
STATIC mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uhashlib_ensure_not_final(self);
|
||||
hashlib_ensure_not_final(self);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
|
||||
SHA1_Update((SHA1_CTX *)self->state, bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
|
||||
STATIC mp_obj_t hashlib_sha1_digest(mp_obj_t self_in) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uhashlib_ensure_not_final(self);
|
||||
hashlib_ensure_not_final(self);
|
||||
self->final = true;
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, SHA1_SIZE);
|
||||
@ -212,36 +211,36 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
|
||||
|
||||
#if MICROPY_SSL_MBEDTLS
|
||||
|
||||
#if MBEDTLS_VERSION_NUMBER < 0x02070000
|
||||
#if MBEDTLS_VERSION_NUMBER < 0x02070000 || MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
#define mbedtls_sha1_starts_ret mbedtls_sha1_starts
|
||||
#define mbedtls_sha1_update_ret mbedtls_sha1_update
|
||||
#define mbedtls_sha1_finish_ret mbedtls_sha1_finish
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t hashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context), type);
|
||||
o->final = false;
|
||||
mbedtls_sha1_init((mbedtls_sha1_context *)o->state);
|
||||
mbedtls_sha1_starts_ret((mbedtls_sha1_context *)o->state);
|
||||
if (n_args == 1) {
|
||||
uhashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
hashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
STATIC mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uhashlib_ensure_not_final(self);
|
||||
hashlib_ensure_not_final(self);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
|
||||
mbedtls_sha1_update_ret((mbedtls_sha1_context *)self->state, bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
|
||||
STATIC mp_obj_t hashlib_sha1_digest(mp_obj_t self_in) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uhashlib_ensure_not_final(self);
|
||||
hashlib_ensure_not_final(self);
|
||||
self->final = true;
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, 20);
|
||||
@ -251,51 +250,51 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(uhashlib_sha1_update_obj, uhashlib_sha1_update);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(uhashlib_sha1_digest_obj, uhashlib_sha1_digest);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(hashlib_sha1_update_obj, hashlib_sha1_update);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(hashlib_sha1_digest_obj, hashlib_sha1_digest);
|
||||
|
||||
STATIC const mp_rom_map_elem_t uhashlib_sha1_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&uhashlib_sha1_update_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&uhashlib_sha1_digest_obj) },
|
||||
STATIC const mp_rom_map_elem_t hashlib_sha1_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&hashlib_sha1_update_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&hashlib_sha1_digest_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(uhashlib_sha1_locals_dict, uhashlib_sha1_locals_dict_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(hashlib_sha1_locals_dict, hashlib_sha1_locals_dict_table);
|
||||
|
||||
STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
uhashlib_sha1_type,
|
||||
hashlib_sha1_type,
|
||||
MP_QSTR_sha1,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, uhashlib_sha1_make_new,
|
||||
locals_dict, &uhashlib_sha1_locals_dict
|
||||
make_new, hashlib_sha1_make_new,
|
||||
locals_dict, &hashlib_sha1_locals_dict
|
||||
);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UHASHLIB_MD5
|
||||
STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg);
|
||||
#if MICROPY_PY_HASHLIB_MD5
|
||||
STATIC mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg);
|
||||
|
||||
#if MICROPY_SSL_AXTLS
|
||||
STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t hashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(MD5_CTX), type);
|
||||
o->final = false;
|
||||
MD5_Init((MD5_CTX *)o->state);
|
||||
if (n_args == 1) {
|
||||
uhashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
hashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
STATIC mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uhashlib_ensure_not_final(self);
|
||||
hashlib_ensure_not_final(self);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
|
||||
MD5_Update((MD5_CTX *)self->state, bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
|
||||
STATIC mp_obj_t hashlib_md5_digest(mp_obj_t self_in) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uhashlib_ensure_not_final(self);
|
||||
hashlib_ensure_not_final(self);
|
||||
self->final = true;
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, MD5_SIZE);
|
||||
@ -312,30 +311,30 @@ STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
|
||||
#define mbedtls_md5_finish_ret mbedtls_md5_finish
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t hashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_md5_context), type);
|
||||
o->final = false;
|
||||
mbedtls_md5_init((mbedtls_md5_context *)o->state);
|
||||
mbedtls_md5_starts_ret((mbedtls_md5_context *)o->state);
|
||||
if (n_args == 1) {
|
||||
uhashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
hashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
STATIC mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uhashlib_ensure_not_final(self);
|
||||
hashlib_ensure_not_final(self);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
|
||||
mbedtls_md5_update_ret((mbedtls_md5_context *)self->state, bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
|
||||
STATIC mp_obj_t hashlib_md5_digest(mp_obj_t self_in) {
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uhashlib_ensure_not_final(self);
|
||||
hashlib_ensure_not_final(self);
|
||||
self->final = true;
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, 16);
|
||||
@ -345,44 +344,44 @@ STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
|
||||
}
|
||||
#endif // MICROPY_SSL_MBEDTLS
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(uhashlib_md5_update_obj, uhashlib_md5_update);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(uhashlib_md5_digest_obj, uhashlib_md5_digest);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(hashlib_md5_update_obj, hashlib_md5_update);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(hashlib_md5_digest_obj, hashlib_md5_digest);
|
||||
|
||||
STATIC const mp_rom_map_elem_t uhashlib_md5_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&uhashlib_md5_update_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&uhashlib_md5_digest_obj) },
|
||||
STATIC const mp_rom_map_elem_t hashlib_md5_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&hashlib_md5_update_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&hashlib_md5_digest_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(uhashlib_md5_locals_dict, uhashlib_md5_locals_dict_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(hashlib_md5_locals_dict, hashlib_md5_locals_dict_table);
|
||||
|
||||
STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
uhashlib_md5_type,
|
||||
hashlib_md5_type,
|
||||
MP_QSTR_md5,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, uhashlib_md5_make_new,
|
||||
locals_dict, &uhashlib_md5_locals_dict
|
||||
make_new, hashlib_md5_make_new,
|
||||
locals_dict, &hashlib_md5_locals_dict
|
||||
);
|
||||
#endif // MICROPY_PY_UHASHLIB_MD5
|
||||
#endif // MICROPY_PY_HASHLIB_MD5
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_uhashlib_globals_table[] = {
|
||||
STATIC const mp_rom_map_elem_t mp_module_hashlib_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_hashlib) },
|
||||
#if MICROPY_PY_UHASHLIB_SHA256
|
||||
{ MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&uhashlib_sha256_type) },
|
||||
#if MICROPY_PY_HASHLIB_SHA256
|
||||
{ MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&hashlib_sha256_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_UHASHLIB_SHA1
|
||||
{ MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&uhashlib_sha1_type) },
|
||||
#if MICROPY_PY_HASHLIB_SHA1
|
||||
{ MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&hashlib_sha1_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_UHASHLIB_MD5
|
||||
{ MP_ROM_QSTR(MP_QSTR_md5), MP_ROM_PTR(&uhashlib_md5_type) },
|
||||
#if MICROPY_PY_HASHLIB_MD5
|
||||
{ MP_ROM_QSTR(MP_QSTR_md5), MP_ROM_PTR(&hashlib_md5_type) },
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_uhashlib_globals, mp_module_uhashlib_globals_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_hashlib_globals, mp_module_hashlib_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uhashlib = {
|
||||
const mp_obj_module_t mp_module_hashlib = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_uhashlib_globals,
|
||||
.globals = (mp_obj_dict_t *)&mp_module_hashlib_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_hashlib, mp_module_uhashlib);
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_hashlib, mp_module_hashlib);
|
||||
|
||||
#endif // MICROPY_PY_UHASHLIB
|
||||
#endif // MICROPY_PY_HASHLIB
|
@ -27,18 +27,18 @@
|
||||
#include "py/objlist.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if MICROPY_PY_UHEAPQ
|
||||
#if MICROPY_PY_HEAPQ
|
||||
|
||||
// the algorithm here is modelled on CPython's heapq.py
|
||||
|
||||
STATIC mp_obj_list_t *uheapq_get_heap(mp_obj_t heap_in) {
|
||||
STATIC mp_obj_list_t *heapq_get_heap(mp_obj_t heap_in) {
|
||||
if (!mp_obj_is_type(heap_in, &mp_type_list)) {
|
||||
mp_raise_TypeError(MP_ERROR_TEXT("heap must be a list"));
|
||||
}
|
||||
return MP_OBJ_TO_PTR(heap_in);
|
||||
}
|
||||
|
||||
STATIC void uheapq_heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) {
|
||||
STATIC void heapq_heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) {
|
||||
mp_obj_t item = heap->items[pos];
|
||||
while (pos > start_pos) {
|
||||
mp_uint_t parent_pos = (pos - 1) >> 1;
|
||||
@ -53,7 +53,7 @@ STATIC void uheapq_heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_ui
|
||||
heap->items[pos] = item;
|
||||
}
|
||||
|
||||
STATIC void uheapq_heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) {
|
||||
STATIC void heapq_heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) {
|
||||
mp_uint_t start_pos = pos;
|
||||
mp_uint_t end_pos = heap->len;
|
||||
mp_obj_t item = heap->items[pos];
|
||||
@ -67,19 +67,19 @@ STATIC void uheapq_heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) {
|
||||
pos = child_pos;
|
||||
}
|
||||
heap->items[pos] = item;
|
||||
uheapq_heap_siftdown(heap, start_pos, pos);
|
||||
heapq_heap_siftdown(heap, start_pos, pos);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mod_uheapq_heappush(mp_obj_t heap_in, mp_obj_t item) {
|
||||
mp_obj_list_t *heap = uheapq_get_heap(heap_in);
|
||||
STATIC mp_obj_t mod_heapq_heappush(mp_obj_t heap_in, mp_obj_t item) {
|
||||
mp_obj_list_t *heap = heapq_get_heap(heap_in);
|
||||
mp_obj_list_append(heap_in, item);
|
||||
uheapq_heap_siftdown(heap, 0, heap->len - 1);
|
||||
heapq_heap_siftdown(heap, 0, heap->len - 1);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_uheapq_heappush_obj, mod_uheapq_heappush);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_heapq_heappush_obj, mod_heapq_heappush);
|
||||
|
||||
STATIC mp_obj_t mod_uheapq_heappop(mp_obj_t heap_in) {
|
||||
mp_obj_list_t *heap = uheapq_get_heap(heap_in);
|
||||
STATIC mp_obj_t mod_heapq_heappop(mp_obj_t heap_in) {
|
||||
mp_obj_list_t *heap = heapq_get_heap(heap_in);
|
||||
if (heap->len == 0) {
|
||||
mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap"));
|
||||
}
|
||||
@ -88,37 +88,37 @@ STATIC mp_obj_t mod_uheapq_heappop(mp_obj_t heap_in) {
|
||||
heap->items[0] = heap->items[heap->len];
|
||||
heap->items[heap->len] = MP_OBJ_NULL; // so we don't retain a pointer
|
||||
if (heap->len) {
|
||||
uheapq_heap_siftup(heap, 0);
|
||||
heapq_heap_siftup(heap, 0);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heappop_obj, mod_uheapq_heappop);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_heapq_heappop_obj, mod_heapq_heappop);
|
||||
|
||||
STATIC mp_obj_t mod_uheapq_heapify(mp_obj_t heap_in) {
|
||||
mp_obj_list_t *heap = uheapq_get_heap(heap_in);
|
||||
STATIC mp_obj_t mod_heapq_heapify(mp_obj_t heap_in) {
|
||||
mp_obj_list_t *heap = heapq_get_heap(heap_in);
|
||||
for (mp_uint_t i = heap->len / 2; i > 0;) {
|
||||
uheapq_heap_siftup(heap, --i);
|
||||
heapq_heap_siftup(heap, --i);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heapify_obj, mod_uheapq_heapify);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_heapq_heapify_obj, mod_heapq_heapify);
|
||||
|
||||
#if !MICROPY_ENABLE_DYNRUNTIME
|
||||
STATIC const mp_rom_map_elem_t mp_module_uheapq_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uheapq) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_heappush), MP_ROM_PTR(&mod_uheapq_heappush_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_heappop), MP_ROM_PTR(&mod_uheapq_heappop_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_heapify), MP_ROM_PTR(&mod_uheapq_heapify_obj) },
|
||||
STATIC const mp_rom_map_elem_t mp_module_heapq_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_heapq) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_heappush), MP_ROM_PTR(&mod_heapq_heappush_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_heappop), MP_ROM_PTR(&mod_heapq_heappop_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_heapify), MP_ROM_PTR(&mod_heapq_heapify_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_uheapq_globals, mp_module_uheapq_globals_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_heapq_globals, mp_module_heapq_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uheapq = {
|
||||
const mp_obj_module_t mp_module_heapq = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_uheapq_globals,
|
||||
.globals = (mp_obj_dict_t *)&mp_module_heapq_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_heapq, mp_module_uheapq);
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_heapq, mp_module_heapq);
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_PY_UHEAPQ
|
||||
#endif // MICROPY_PY_HEAPQ
|
@ -26,24 +26,22 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/binary.h"
|
||||
#include "py/objarray.h"
|
||||
#include "py/objlist.h"
|
||||
#include "py/objstringio.h"
|
||||
#include "py/parsenum.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
#if MICROPY_PY_UJSON
|
||||
#if MICROPY_PY_JSON
|
||||
|
||||
#if MICROPY_PY_UJSON_SEPARATORS
|
||||
#if MICROPY_PY_JSON_SEPARATORS
|
||||
|
||||
enum {
|
||||
DUMP_MODE_TO_STRING = 1,
|
||||
DUMP_MODE_TO_STREAM = 2,
|
||||
};
|
||||
|
||||
STATIC mp_obj_t mod_ujson_dump_helper(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, unsigned int mode) {
|
||||
STATIC mp_obj_t mod_json_dump_helper(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, unsigned int mode) {
|
||||
enum { ARG_separators };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_separators, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
@ -80,34 +78,35 @@ STATIC mp_obj_t mod_ujson_dump_helper(size_t n_args, const mp_obj_t *pos_args, m
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mod_ujson_dump(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
return mod_ujson_dump_helper(n_args, pos_args, kw_args, DUMP_MODE_TO_STREAM);
|
||||
STATIC mp_obj_t mod_json_dump(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
return mod_json_dump_helper(n_args, pos_args, kw_args, DUMP_MODE_TO_STREAM);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ujson_dump_obj, 2, mod_ujson_dump);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_json_dump_obj, 2, mod_json_dump);
|
||||
|
||||
STATIC mp_obj_t mod_ujson_dumps(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
return mod_ujson_dump_helper(n_args, pos_args, kw_args, DUMP_MODE_TO_STRING);
|
||||
STATIC mp_obj_t mod_json_dumps(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
return mod_json_dump_helper(n_args, pos_args, kw_args, DUMP_MODE_TO_STRING);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ujson_dumps_obj, 1, mod_ujson_dumps);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_json_dumps_obj, 1, mod_json_dumps);
|
||||
|
||||
#else
|
||||
|
||||
STATIC mp_obj_t mod_ujson_dump(mp_obj_t obj, mp_obj_t stream) {
|
||||
STATIC mp_obj_t mod_json_dump(mp_obj_t obj, mp_obj_t stream) {
|
||||
mp_get_stream_raise(stream, MP_STREAM_OP_WRITE);
|
||||
mp_print_t print = {MP_OBJ_TO_PTR(stream), mp_stream_write_adaptor};
|
||||
mp_obj_print_helper(&print, obj, PRINT_JSON);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ujson_dump_obj, mod_ujson_dump);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_json_dump_obj, mod_json_dump);
|
||||
|
||||
STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) {
|
||||
STATIC mp_obj_t mod_json_dumps(mp_obj_t obj) {
|
||||
vstr_t vstr;
|
||||
mp_print_t print;
|
||||
vstr_init_print(&vstr, 8, &print);
|
||||
mp_obj_print_helper(&print, obj, PRINT_JSON);
|
||||
return mp_obj_new_str_from_utf8_vstr(&vstr);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_json_dumps_obj, mod_json_dumps);
|
||||
|
||||
#endif
|
||||
|
||||
#define JSON_DEBUG(...) (void)0
|
||||
@ -127,7 +126,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps);
|
||||
// strings). It does 1 pass over the input stream. It tries to be fast and
|
||||
// small in code size, while not using more RAM than necessary.
|
||||
|
||||
typedef struct _ujson_stream_t {
|
||||
typedef struct _json_stream_t {
|
||||
mp_obj_t stream_obj;
|
||||
mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
|
||||
int errcode;
|
||||
@ -137,16 +136,15 @@ typedef struct _ujson_stream_t {
|
||||
size_t start;
|
||||
size_t end;
|
||||
byte cur;
|
||||
} ujson_stream_t;
|
||||
} json_stream_t;
|
||||
|
||||
#define S_EOF (0) // null is not allowed in json stream so is ok as EOF marker
|
||||
#define S_END(s) ((s).cur == S_EOF)
|
||||
#define S_CUR(s) ((s).cur)
|
||||
#define S_NEXT(s) (ujson_stream_next(&(s)))
|
||||
#define S_NEXT(s) (json_stream_next(&(s)))
|
||||
|
||||
STATIC byte ujson_stream_next(ujson_stream_t *s) {
|
||||
STATIC byte json_stream_next(json_stream_t *s) {
|
||||
mp_uint_t ret = s->read(s->stream_obj, &s->cur, 1, &s->errcode);
|
||||
JSON_DEBUG(" usjon_stream_next err:%2d cur: %c \n", s->errcode, s->cur);
|
||||
if (s->errcode != 0) {
|
||||
mp_raise_OSError(s->errcode);
|
||||
}
|
||||
@ -163,7 +161,7 @@ STATIC byte ujson_stream_next(ujson_stream_t *s) {
|
||||
|
||||
#define CIRCUITPY_JSON_READ_CHUNK_SIZE 64
|
||||
|
||||
STATIC mp_uint_t ujson_python_readinto(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode) {
|
||||
STATIC mp_uint_t json_python_readinto(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode) {
|
||||
(void)size; // Ignore size because we know it's always 1.
|
||||
ujson_stream_t *s = obj;
|
||||
|
||||
@ -186,7 +184,7 @@ STATIC mp_uint_t ujson_python_readinto(mp_obj_t obj, void *buf, mp_uint_t size,
|
||||
return 1;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t _mod_ujson_load(mp_obj_t stream_obj, bool return_first_json) {
|
||||
STATIC mp_obj_t _mod_json_load(mp_obj_t stream_obj, bool return_first_json) {
|
||||
const mp_stream_p_t *stream_p = mp_proto_get(MP_QSTR_protocol_stream, stream_obj);
|
||||
ujson_stream_t s;
|
||||
uint8_t character_buffer[CIRCUITPY_JSON_READ_CHUNK_SIZE];
|
||||
@ -426,39 +424,35 @@ fail:
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("syntax error in JSON"));
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
|
||||
return _mod_ujson_load(stream_obj, true);
|
||||
STATIC mp_obj_t mod_json_load(mp_obj_t stream_obj) {
|
||||
return _mod_json_load(stream_obj, true);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_json_load_obj, mod_json_load);
|
||||
|
||||
STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
|
||||
STATIC mp_obj_t mod_json_loads(mp_obj_t obj) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(obj, &bufinfo, MP_BUFFER_READ);
|
||||
vstr_t vstr = {bufinfo.len, bufinfo.len, (char *)bufinfo.buf, true};
|
||||
mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0, MP_OBJ_NULL};
|
||||
return _mod_ujson_load(MP_OBJ_FROM_PTR(&sio), false);
|
||||
return mod_json_load(MP_OBJ_FROM_PTR(&sio));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_loads_obj, mod_ujson_loads);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_json_loads_obj, mod_json_loads);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_ujson_globals_table[] = {
|
||||
#if CIRCUITPY
|
||||
STATIC const mp_rom_map_elem_t mp_module_json_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_json) },
|
||||
#else
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ujson) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_ujson_dump_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_dumps), MP_ROM_PTR(&mod_ujson_dumps_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_load), MP_ROM_PTR(&mod_ujson_load_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_loads), MP_ROM_PTR(&mod_ujson_loads_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_json_dump_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_dumps), MP_ROM_PTR(&mod_json_dumps_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_load), MP_ROM_PTR(&mod_json_load_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_loads), MP_ROM_PTR(&mod_json_loads_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_ujson_globals, mp_module_ujson_globals_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_json_globals, mp_module_json_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_ujson = {
|
||||
const mp_obj_module_t mp_module_json = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_ujson_globals,
|
||||
.globals = (mp_obj_dict_t *)&mp_module_json_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_json, mp_module_ujson);
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_json, mp_module_json);
|
||||
|
||||
#endif // MICROPY_PY_UJSON
|
||||
#endif // MICROPY_PY_JSON
|
@ -27,13 +27,17 @@
|
||||
#include "py/objstr.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if MICROPY_PY_UOS
|
||||
#if MICROPY_PY_OS
|
||||
|
||||
#include "extmod/misc.h"
|
||||
#include "extmod/vfs.h"
|
||||
|
||||
#if MICROPY_VFS_FAT
|
||||
#include "extmod/vfs_fat.h"
|
||||
#if MICROPY_PY_OS_SYNC
|
||||
#include "lib/oofatfs/ff.h"
|
||||
#include "lib/oofatfs/diskio.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2
|
||||
@ -44,12 +48,12 @@
|
||||
#include "extmod/vfs_posix.h"
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UOS_UNAME
|
||||
#if MICROPY_PY_OS_UNAME
|
||||
#include "genhdr/mpversion.h"
|
||||
#endif
|
||||
|
||||
#ifdef MICROPY_PY_UOS_INCLUDEFILE
|
||||
#include MICROPY_PY_UOS_INCLUDEFILE
|
||||
#ifdef MICROPY_PY_OS_INCLUDEFILE
|
||||
#include MICROPY_PY_OS_INCLUDEFILE
|
||||
#endif
|
||||
|
||||
#ifdef MICROPY_BUILD_TYPE
|
||||
@ -58,77 +62,87 @@
|
||||
#define MICROPY_BUILD_TYPE_PAREN
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UOS_UNAME
|
||||
#if MICROPY_PY_OS_SYNC
|
||||
// sync()
|
||||
// Sync all filesystems.
|
||||
STATIC mp_obj_t mp_os_sync(void) {
|
||||
#if MICROPY_VFS_FAT
|
||||
for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) {
|
||||
// this assumes that vfs->obj is fs_user_mount_t with block device functions
|
||||
disk_ioctl(MP_OBJ_TO_PTR(vfs->obj), CTRL_SYNC, NULL);
|
||||
}
|
||||
#endif
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_os_sync_obj, mp_os_sync);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UOS_UNAME_RELEASE_DYNAMIC
|
||||
#if MICROPY_PY_OS_UNAME
|
||||
|
||||
#if MICROPY_PY_OS_UNAME_RELEASE_DYNAMIC
|
||||
#define CONST_RELEASE
|
||||
#else
|
||||
#define CONST_RELEASE const
|
||||
#endif
|
||||
|
||||
STATIC const qstr mp_uos_uname_info_fields[] = {
|
||||
STATIC const qstr mp_os_uname_info_fields[] = {
|
||||
MP_QSTR_sysname,
|
||||
MP_QSTR_nodename,
|
||||
MP_QSTR_release,
|
||||
MP_QSTR_version,
|
||||
MP_QSTR_machine
|
||||
};
|
||||
STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM);
|
||||
STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM);
|
||||
STATIC CONST_RELEASE MP_DEFINE_STR_OBJ(mp_uos_uname_info_release_obj, MICROPY_VERSION_STRING);
|
||||
STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE MICROPY_BUILD_TYPE_PAREN);
|
||||
STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
|
||||
STATIC const MP_DEFINE_STR_OBJ(mp_os_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM);
|
||||
STATIC const MP_DEFINE_STR_OBJ(mp_os_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM);
|
||||
STATIC CONST_RELEASE MP_DEFINE_STR_OBJ(mp_os_uname_info_release_obj, MICROPY_VERSION_STRING);
|
||||
STATIC const MP_DEFINE_STR_OBJ(mp_os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE MICROPY_BUILD_TYPE_PAREN);
|
||||
STATIC const MP_DEFINE_STR_OBJ(mp_os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
|
||||
|
||||
STATIC MP_DEFINE_ATTRTUPLE(
|
||||
mp_uos_uname_info_obj,
|
||||
mp_uos_uname_info_fields,
|
||||
mp_os_uname_info_obj,
|
||||
mp_os_uname_info_fields,
|
||||
5,
|
||||
MP_ROM_PTR(&mp_uos_uname_info_sysname_obj),
|
||||
MP_ROM_PTR(&mp_uos_uname_info_nodename_obj),
|
||||
MP_ROM_PTR(&mp_uos_uname_info_release_obj),
|
||||
MP_ROM_PTR(&mp_uos_uname_info_version_obj),
|
||||
MP_ROM_PTR(&mp_uos_uname_info_machine_obj)
|
||||
MP_ROM_PTR(&mp_os_uname_info_sysname_obj),
|
||||
MP_ROM_PTR(&mp_os_uname_info_nodename_obj),
|
||||
MP_ROM_PTR(&mp_os_uname_info_release_obj),
|
||||
MP_ROM_PTR(&mp_os_uname_info_version_obj),
|
||||
MP_ROM_PTR(&mp_os_uname_info_machine_obj)
|
||||
);
|
||||
|
||||
STATIC mp_obj_t mp_uos_uname(void) {
|
||||
#if MICROPY_PY_UOS_UNAME_RELEASE_DYNAMIC
|
||||
const char *release = mp_uos_uname_release();
|
||||
mp_uos_uname_info_release_obj.len = strlen(release);
|
||||
mp_uos_uname_info_release_obj.data = (const byte *)release;
|
||||
STATIC mp_obj_t mp_os_uname(void) {
|
||||
#if MICROPY_PY_OS_UNAME_RELEASE_DYNAMIC
|
||||
const char *release = mp_os_uname_release();
|
||||
mp_os_uname_info_release_obj.len = strlen(release);
|
||||
mp_os_uname_info_release_obj.data = (const byte *)release;
|
||||
#endif
|
||||
return MP_OBJ_FROM_PTR(&mp_uos_uname_info_obj);
|
||||
return MP_OBJ_FROM_PTR(&mp_os_uname_info_obj);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_uos_uname_obj, mp_uos_uname);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_os_uname_obj, mp_os_uname);
|
||||
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_os) },
|
||||
|
||||
#if MICROPY_PY_UOS_GETENV_PUTENV_UNSETENV
|
||||
{ MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mp_uos_getenv_obj) },
|
||||
#if defined(MICROPY_UNIX_COVERAGE)
|
||||
{ MP_ROM_QSTR(MP_QSTR_getenv_int), MP_ROM_PTR(&mp_uos_getenv_int_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_getenv_str), MP_ROM_PTR(&mp_uos_getenv_str_obj) },
|
||||
#if MICROPY_PY_OS_GETENV_PUTENV_UNSETENV
|
||||
{ MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mp_os_getenv_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_putenv), MP_ROM_PTR(&mp_os_putenv_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unsetenv), MP_ROM_PTR(&mp_os_unsetenv_obj) },
|
||||
#endif
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_putenv), MP_ROM_PTR(&mp_uos_putenv_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unsetenv), MP_ROM_PTR(&mp_uos_unsetenv_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_SEP
|
||||
#if MICROPY_PY_OS_SEP
|
||||
{ MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_SYNC
|
||||
{ MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mp_uos_sync_obj) },
|
||||
#if MICROPY_PY_OS_SYNC
|
||||
{ MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mp_os_sync_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_SYSTEM
|
||||
{ MP_ROM_QSTR(MP_QSTR_system), MP_ROM_PTR(&mp_uos_system_obj) },
|
||||
#if MICROPY_PY_OS_SYSTEM
|
||||
{ MP_ROM_QSTR(MP_QSTR_system), MP_ROM_PTR(&mp_os_system_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_UNAME
|
||||
{ MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&mp_uos_uname_obj) },
|
||||
#if MICROPY_PY_OS_UNAME
|
||||
{ MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&mp_os_uname_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_URANDOM
|
||||
{ MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&mp_uos_urandom_obj) },
|
||||
#if MICROPY_PY_OS_URANDOM
|
||||
{ MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&mp_os_urandom_obj) },
|
||||
#endif
|
||||
|
||||
#if MICROPY_VFS
|
||||
@ -147,13 +161,13 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
|
||||
// The following are MicroPython extensions.
|
||||
|
||||
#if MICROPY_PY_OS_DUPTERM
|
||||
{ MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_os_dupterm_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_DUPTERM_NOTIFY
|
||||
{ MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&mp_uos_dupterm_notify_obj) },
|
||||
#if MICROPY_PY_OS_DUPTERM_NOTIFY
|
||||
{ MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&mp_os_dupterm_notify_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_ERRNO
|
||||
{ MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_uos_errno_obj) },
|
||||
#if MICROPY_PY_OS_ERRNO
|
||||
{ MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_os_errno_obj) },
|
||||
#endif
|
||||
|
||||
#if MICROPY_VFS
|
||||
@ -176,11 +190,11 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uos = {
|
||||
const mp_obj_module_t mp_module_os = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&os_module_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_os, mp_module_uos);
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_os, mp_module_os);
|
||||
|
||||
#endif // MICROPY_PY_UOS
|
||||
#endif // MICROPY_PY_OS
|
@ -29,10 +29,10 @@
|
||||
#include "py/objtuple.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/moduplatform.h"
|
||||
#include "extmod/modplatform.h"
|
||||
#include "genhdr/mpversion.h"
|
||||
|
||||
#if MICROPY_PY_UPLATFORM
|
||||
#if MICROPY_PY_PLATFORM
|
||||
|
||||
// platform - Access to underlying platform's identifying data
|
||||
|
||||
@ -62,7 +62,7 @@ STATIC mp_obj_t platform_libc_ver(size_t n_args, const mp_obj_t *pos_args, mp_ma
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(platform_libc_ver_obj, 0, platform_libc_ver);
|
||||
|
||||
STATIC const mp_rom_map_elem_t modplatform_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uplatform) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_platform) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_platform_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_python_compiler), MP_ROM_PTR(&platform_python_compiler_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_libc_ver), MP_ROM_PTR(&platform_libc_ver_obj) },
|
||||
@ -70,11 +70,11 @@ STATIC const mp_rom_map_elem_t modplatform_globals_table[] = {
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(modplatform_globals, modplatform_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uplatform = {
|
||||
const mp_obj_module_t mp_module_platform = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&modplatform_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_platform, mp_module_uplatform);
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_platform, mp_module_platform);
|
||||
|
||||
#endif // MICROPY_PY_UPLATFORM
|
||||
#endif // MICROPY_PY_PLATFORM
|
@ -23,14 +23,14 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_MODUPLATFORM_H
|
||||
#define MICROPY_INCLUDED_MODUPLATFORM_H
|
||||
#ifndef MICROPY_INCLUDED_MODPLATFORM_H
|
||||
#define MICROPY_INCLUDED_MODPLATFORM_H
|
||||
|
||||
#include "py/misc.h" // For MP_STRINGIFY.
|
||||
#include "py/mpconfig.h"
|
||||
|
||||
// Preprocessor directives identifying the platform.
|
||||
// The (u)platform module itself is guarded by MICROPY_PY_UPLATFORM, see the
|
||||
// The platform module itself is guarded by MICROPY_PY_PLATFORM, see the
|
||||
// .c file, but these are made available because they're generally usable.
|
||||
// TODO: Add more architectures, compilers and libraries.
|
||||
// See: https://sourceforge.net/p/predef/wiki/Home/
|
||||
@ -43,6 +43,8 @@
|
||||
#define MICROPY_PLATFORM_ARCH "x86"
|
||||
#elif defined(__xtensa__)
|
||||
#define MICROPY_PLATFORM_ARCH "xtensa"
|
||||
#elif defined(__riscv)
|
||||
#define MICROPY_PLATFORM_ARCH "riscv"
|
||||
#else
|
||||
#define MICROPY_PLATFORM_ARCH ""
|
||||
#endif
|
||||
@ -102,4 +104,4 @@
|
||||
#define MICROPY_PLATFORM_VERSION ""
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_INCLUDED_MODUPLATFORM_H
|
||||
#endif // MICROPY_INCLUDED_MODPLATFORM_H
|
@ -29,10 +29,10 @@
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if MICROPY_PY_URANDOM
|
||||
#if MICROPY_PY_RANDOM
|
||||
|
||||
// Work out if the seed will be set on import or not.
|
||||
#if MICROPY_MODULE_BUILTIN_INIT && defined(MICROPY_PY_URANDOM_SEED_INIT_FUNC)
|
||||
#if MICROPY_MODULE_BUILTIN_INIT && defined(MICROPY_PY_RANDOM_SEED_INIT_FUNC)
|
||||
#define SEED_ON_IMPORT (1)
|
||||
#else
|
||||
#define SEED_ON_IMPORT (0)
|
||||
@ -255,7 +255,7 @@ const mp_obj_module_t mp_module_urandom = {
|
||||
.globals = (mp_obj_dict_t *)&mp_module_urandom_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_random, mp_module_urandom);
|
||||
MP_REGISTER_MODULE(MP_QSTR_urandom, mp_module_urandom);
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_PY_URANDOM
|
@ -37,7 +37,7 @@
|
||||
#include "py/unicode.h"
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_URE
|
||||
#if MICROPY_PY_RE
|
||||
|
||||
#define re1_5_stack_chk() MP_STACK_CHECK()
|
||||
|
||||
@ -167,10 +167,10 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_end_obj, 1, 2, match_end);
|
||||
#if !MICROPY_ENABLE_DYNRUNTIME
|
||||
STATIC const mp_rom_map_elem_t match_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_group), MP_ROM_PTR(&match_group_obj) },
|
||||
#if MICROPY_PY_URE_MATCH_GROUPS
|
||||
#if MICROPY_PY_RE_MATCH_GROUPS
|
||||
{ MP_ROM_QSTR(MP_QSTR_groups), MP_ROM_PTR(&match_groups_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_URE_MATCH_SPAN_START_END
|
||||
#if MICROPY_PY_RE_MATCH_SPAN_START_END
|
||||
{ MP_ROM_QSTR(MP_QSTR_span), MP_ROM_PTR(&match_span_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&match_start_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_end), MP_ROM_PTR(&match_end_obj) },
|
||||
@ -194,7 +194,7 @@ STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
|
||||
mp_printf(print, "<re %p>", self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
mp_obj_re_t *self;
|
||||
if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) {
|
||||
@ -206,7 +206,8 @@ STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
|
||||
size_t len;
|
||||
subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len);
|
||||
subj.end = subj.begin + len;
|
||||
#if MICROPY_PY_URE_MATCH_SPAN_START_END && !(defined(MICROPY_ENABLE_DYNRUNTIME) && MICROPY_ENABLE_DYNRUNTIME)
|
||||
// CIRCUITPY
|
||||
#if MICROPY_PY_RE_MATCH_SPAN_START_END && !(defined(MICROPY_ENABLE_DYNRUNTIME) && MICROPY_ENABLE_DYNRUNTIME)
|
||||
|
||||
if (n_args > 2) {
|
||||
const mp_obj_type_t *self_type = mp_obj_get_type(args[1]);
|
||||
@ -253,12 +254,12 @@ STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
|
||||
}
|
||||
|
||||
STATIC mp_obj_t re_match(size_t n_args, const mp_obj_t *args) {
|
||||
return ure_exec(true, n_args, args);
|
||||
return re_exec(true, n_args, args);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_match_obj, 2, 4, re_match);
|
||||
|
||||
STATIC mp_obj_t re_search(size_t n_args, const mp_obj_t *args) {
|
||||
return ure_exec(false, n_args, args);
|
||||
return re_exec(false, n_args, args);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_search_obj, 2, 4, re_search);
|
||||
|
||||
@ -307,7 +308,7 @@ STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_split_obj, 2, 3, re_split);
|
||||
|
||||
#if MICROPY_PY_URE_SUB
|
||||
#if MICROPY_PY_RE_SUB
|
||||
|
||||
STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_re_t *self;
|
||||
@ -435,7 +436,7 @@ STATIC const mp_rom_map_elem_t re_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&re_match_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&re_search_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_split), MP_ROM_PTR(&re_split_obj) },
|
||||
#if MICROPY_PY_URE_SUB
|
||||
#if MICROPY_PY_RE_SUB
|
||||
{ MP_ROM_QSTR(MP_QSTR_sub), MP_ROM_PTR(&re_sub_obj) },
|
||||
#endif
|
||||
};
|
||||
@ -444,11 +445,7 @@ STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table);
|
||||
|
||||
STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
re_type,
|
||||
#if CIRCUITPY
|
||||
MP_QSTR_re,
|
||||
#else
|
||||
MP_QSTR_ure,
|
||||
#endif
|
||||
MP_TYPE_FLAG_NONE,
|
||||
print, re_print,
|
||||
locals_dict, &re_locals_dict
|
||||
@ -463,7 +460,7 @@ STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) {
|
||||
goto error;
|
||||
}
|
||||
mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, char, size, (mp_obj_type_t *)&re_type);
|
||||
#if MICROPY_PY_URE_DEBUG
|
||||
#if MICROPY_PY_RE_DEBUG
|
||||
int flags = 0;
|
||||
if (n_args > 1) {
|
||||
flags = mp_obj_get_int(args[1]);
|
||||
@ -474,7 +471,7 @@ STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) {
|
||||
error:
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Error in regex"));
|
||||
}
|
||||
#if MICROPY_PY_URE_DEBUG
|
||||
#if MICROPY_PY_RE_DEBUG
|
||||
if (flags & FLAG_DEBUG) {
|
||||
re1_5_dumpcode(&o->re);
|
||||
}
|
||||
@ -485,30 +482,26 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_compile_obj, 1, 2, mod_re_compile);
|
||||
|
||||
#if !MICROPY_ENABLE_DYNRUNTIME
|
||||
STATIC const mp_rom_map_elem_t mp_module_re_globals_table[] = {
|
||||
#if CIRCUITPY
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_re) },
|
||||
#else
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ure) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_compile), MP_ROM_PTR(&mod_re_compile_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&re_match_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&re_search_obj) },
|
||||
#if MICROPY_PY_URE_SUB
|
||||
#if MICROPY_PY_RE_SUB
|
||||
{ MP_ROM_QSTR(MP_QSTR_sub), MP_ROM_PTR(&re_sub_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_URE_DEBUG
|
||||
#if MICROPY_PY_RE_DEBUG
|
||||
{ MP_ROM_QSTR(MP_QSTR_DEBUG), MP_ROM_INT(FLAG_DEBUG) },
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_re_globals, mp_module_re_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_ure = {
|
||||
const mp_obj_module_t mp_module_re = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_re_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_re, mp_module_ure);
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_re, mp_module_re);
|
||||
#endif
|
||||
|
||||
// Source files #include'd here to make sure they're compiled in
|
||||
@ -520,11 +513,11 @@ MP_REGISTER_MODULE(MP_QSTR_re, mp_module_ure);
|
||||
#include "lib/re1.5/recursiveloop.c"
|
||||
#include "lib/re1.5/charclass.c"
|
||||
|
||||
#if MICROPY_PY_URE_DEBUG
|
||||
#if MICROPY_PY_RE_DEBUG
|
||||
// Make sure the output print statements go to the same output as other Python output.
|
||||
#define printf(...) mp_printf(&mp_plat_print, __VA_ARGS__)
|
||||
#include "lib/re1.5/dumpcode.c"
|
||||
#undef printf
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_PY_URE
|
||||
#endif // MICROPY_PY_RE
|
646
extmod/modselect.c
Normal file
646
extmod/modselect.c
Normal file
@ -0,0 +1,646 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2023 Damien P. George
|
||||
* Copyright (c) 2015-2017 Paul Sokolovsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/objlist.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/mphal.h"
|
||||
#include "shared/runtime/interrupt_char.h"
|
||||
|
||||
#if MICROPY_PY_SELECT
|
||||
|
||||
#if MICROPY_PY_SELECT_SELECT && MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
|
||||
#error "select.select is not supported with MICROPY_PY_SELECT_POSIX_OPTIMISATIONS"
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
|
||||
|
||||
#include <poll.h>
|
||||
|
||||
#if !((MP_STREAM_POLL_RD) == (POLLIN) && \
|
||||
(MP_STREAM_POLL_WR) == (POLLOUT) && \
|
||||
(MP_STREAM_POLL_ERR) == (POLLERR) && \
|
||||
(MP_STREAM_POLL_HUP) == (POLLHUP) && \
|
||||
(MP_STREAM_POLL_NVAL) == (POLLNVAL))
|
||||
#error "With MICROPY_PY_SELECT_POSIX_OPTIMISATIONS enabled, POLL constants must match"
|
||||
#endif
|
||||
|
||||
// When non-file-descriptor objects are on the list to be polled (the polling of
|
||||
// which involves repeatedly calling ioctl(MP_STREAM_POLL)), this variable sets
|
||||
// the period between polling these objects.
|
||||
#define MICROPY_PY_SELECT_IOCTL_CALL_PERIOD_MS (1)
|
||||
|
||||
#endif
|
||||
|
||||
// Flags for ipoll()
|
||||
#define FLAG_ONESHOT (1)
|
||||
|
||||
// A single pollable object.
|
||||
typedef struct _poll_obj_t {
|
||||
mp_obj_t obj;
|
||||
mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
|
||||
#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
|
||||
// If the pollable object has an associated file descriptor, then pollfd points to an entry
|
||||
// in poll_set_t::pollfds, and the events/revents fields for this object are stored in the
|
||||
// pollfd entry (and the nonfd_* members are unused).
|
||||
// Otherwise the object is a non-file-descriptor object and pollfd==NULL, and the events/
|
||||
// revents fields are stored in the nonfd_* members (which are named as such so that code
|
||||
// doesn't accidentally mix the use of these members when this optimisation is used).
|
||||
struct pollfd *pollfd;
|
||||
uint16_t nonfd_events;
|
||||
uint16_t nonfd_revents;
|
||||
#else
|
||||
mp_uint_t events;
|
||||
mp_uint_t revents;
|
||||
#endif
|
||||
} poll_obj_t;
|
||||
|
||||
// A set of pollable objects.
|
||||
typedef struct _poll_set_t {
|
||||
// Map containing a dict with key=object to poll, value=its corresponding poll_obj_t.
|
||||
mp_map_t map;
|
||||
|
||||
#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
|
||||
// Array of pollfd entries for objects that have a file descriptor.
|
||||
unsigned short alloc; // memory allocated for pollfds
|
||||
unsigned short max_used; // maximum number of used entries in pollfds
|
||||
unsigned short used; // actual number of used entries in pollfds
|
||||
struct pollfd *pollfds;
|
||||
#endif
|
||||
} poll_set_t;
|
||||
|
||||
STATIC void poll_set_init(poll_set_t *poll_set, size_t n) {
|
||||
mp_map_init(&poll_set->map, n);
|
||||
#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
|
||||
poll_set->alloc = 0;
|
||||
poll_set->max_used = 0;
|
||||
poll_set->used = 0;
|
||||
poll_set->pollfds = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MICROPY_PY_SELECT_SELECT
|
||||
STATIC void poll_set_deinit(poll_set_t *poll_set) {
|
||||
mp_map_deinit(&poll_set->map);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
|
||||
|
||||
STATIC mp_uint_t poll_obj_get_events(poll_obj_t *poll_obj) {
|
||||
assert(poll_obj->pollfd == NULL);
|
||||
return poll_obj->nonfd_events;
|
||||
}
|
||||
|
||||
STATIC void poll_obj_set_events(poll_obj_t *poll_obj, mp_uint_t events) {
|
||||
if (poll_obj->pollfd != NULL) {
|
||||
poll_obj->pollfd->events = events;
|
||||
} else {
|
||||
poll_obj->nonfd_events = events;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_uint_t poll_obj_get_revents(poll_obj_t *poll_obj) {
|
||||
if (poll_obj->pollfd != NULL) {
|
||||
return poll_obj->pollfd->revents;
|
||||
} else {
|
||||
return poll_obj->nonfd_revents;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void poll_obj_set_revents(poll_obj_t *poll_obj, mp_uint_t revents) {
|
||||
if (poll_obj->pollfd != NULL) {
|
||||
poll_obj->pollfd->revents = revents;
|
||||
} else {
|
||||
poll_obj->nonfd_revents = revents;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC struct pollfd *poll_set_add_fd(poll_set_t *poll_set, int fd) {
|
||||
struct pollfd *free_slot = NULL;
|
||||
|
||||
if (poll_set->used == poll_set->max_used) {
|
||||
// No free slots below max_used, so expand max_used (and possibly allocate).
|
||||
if (poll_set->max_used >= poll_set->alloc) {
|
||||
poll_set->pollfds = m_renew(struct pollfd, poll_set->pollfds, poll_set->alloc, poll_set->alloc + 4);
|
||||
poll_set->alloc += 4;
|
||||
}
|
||||
free_slot = &poll_set->pollfds[poll_set->max_used++];
|
||||
} else {
|
||||
// There should be a free slot below max_used.
|
||||
for (unsigned int i = 0; i < poll_set->max_used; ++i) {
|
||||
struct pollfd *slot = &poll_set->pollfds[i];
|
||||
if (slot->fd == -1) {
|
||||
free_slot = slot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(free_slot != NULL);
|
||||
}
|
||||
|
||||
free_slot->fd = fd;
|
||||
++poll_set->used;
|
||||
|
||||
return free_slot;
|
||||
}
|
||||
|
||||
static inline bool poll_set_all_are_fds(poll_set_t *poll_set) {
|
||||
return poll_set->map.used == poll_set->used;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline mp_uint_t poll_obj_get_events(poll_obj_t *poll_obj) {
|
||||
return poll_obj->events;
|
||||
}
|
||||
|
||||
static inline void poll_obj_set_events(poll_obj_t *poll_obj, mp_uint_t events) {
|
||||
poll_obj->events = events;
|
||||
}
|
||||
|
||||
static inline mp_uint_t poll_obj_get_revents(poll_obj_t *poll_obj) {
|
||||
return poll_obj->revents;
|
||||
}
|
||||
|
||||
static inline void poll_obj_set_revents(poll_obj_t *poll_obj, mp_uint_t revents) {
|
||||
poll_obj->revents = revents;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
STATIC void poll_set_add_obj(poll_set_t *poll_set, const mp_obj_t *obj, mp_uint_t obj_len, mp_uint_t events, bool or_events) {
|
||||
for (mp_uint_t i = 0; i < obj_len; i++) {
|
||||
mp_map_elem_t *elem = mp_map_lookup(&poll_set->map, mp_obj_id(obj[i]), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
|
||||
if (elem->value == MP_OBJ_NULL) {
|
||||
// object not found; get its ioctl and add it to the poll list
|
||||
|
||||
// If an exception is raised below when adding the new object then the map entry for that
|
||||
// object remains unpopulated, and methods like poll() may crash. This case is not handled.
|
||||
|
||||
poll_obj_t *poll_obj = m_new_obj(poll_obj_t);
|
||||
poll_obj->obj = obj[i];
|
||||
|
||||
#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
|
||||
int fd = -1;
|
||||
if (mp_obj_is_int(obj[i])) {
|
||||
// A file descriptor integer passed in as the object, so use it directly.
|
||||
fd = mp_obj_get_int(obj[i]);
|
||||
if (fd < 0) {
|
||||
mp_raise_ValueError(NULL);
|
||||
}
|
||||
poll_obj->ioctl = NULL;
|
||||
} else {
|
||||
// An object passed in. Check if it has a file descriptor.
|
||||
const mp_stream_p_t *stream_p = mp_get_stream_raise(obj[i], MP_STREAM_OP_IOCTL);
|
||||
poll_obj->ioctl = stream_p->ioctl;
|
||||
int err;
|
||||
mp_uint_t res = stream_p->ioctl(obj[i], MP_STREAM_GET_FILENO, 0, &err);
|
||||
if (res != MP_STREAM_ERROR) {
|
||||
fd = res;
|
||||
}
|
||||
}
|
||||
if (fd >= 0) {
|
||||
// Object has a file descriptor so add it to pollfds.
|
||||
poll_obj->pollfd = poll_set_add_fd(poll_set, fd);
|
||||
} else {
|
||||
// Object doesn't have a file descriptor.
|
||||
poll_obj->pollfd = NULL;
|
||||
}
|
||||
#else
|
||||
const mp_stream_p_t *stream_p = mp_get_stream_raise(obj[i], MP_STREAM_OP_IOCTL);
|
||||
poll_obj->ioctl = stream_p->ioctl;
|
||||
#endif
|
||||
|
||||
poll_obj_set_events(poll_obj, events);
|
||||
poll_obj_set_revents(poll_obj, 0);
|
||||
elem->value = MP_OBJ_FROM_PTR(poll_obj);
|
||||
} else {
|
||||
// object exists; update its events
|
||||
poll_obj_t *poll_obj = (poll_obj_t *)MP_OBJ_TO_PTR(elem->value);
|
||||
#if MICROPY_PY_SELECT_SELECT
|
||||
if (or_events) {
|
||||
events |= poll_obj_get_events(poll_obj);
|
||||
}
|
||||
#else
|
||||
(void)or_events;
|
||||
#endif
|
||||
poll_obj_set_events(poll_obj, events);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For each object in the poll set, poll it once.
|
||||
STATIC mp_uint_t poll_set_poll_once(poll_set_t *poll_set, size_t *rwx_num) {
|
||||
mp_uint_t n_ready = 0;
|
||||
for (mp_uint_t i = 0; i < poll_set->map.alloc; ++i) {
|
||||
if (!mp_map_slot_is_filled(&poll_set->map, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_set->map.table[i].value);
|
||||
|
||||
#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
|
||||
if (poll_obj->pollfd != NULL) {
|
||||
// Object has file descriptor so will be polled separately by poll().
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
int errcode;
|
||||
mp_int_t ret = poll_obj->ioctl(poll_obj->obj, MP_STREAM_POLL, poll_obj_get_events(poll_obj), &errcode);
|
||||
poll_obj_set_revents(poll_obj, ret);
|
||||
|
||||
if (ret == -1) {
|
||||
// error doing ioctl
|
||||
mp_raise_OSError(errcode);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
// object is ready
|
||||
n_ready += 1;
|
||||
#if MICROPY_PY_SELECT_SELECT
|
||||
if (rwx_num != NULL) {
|
||||
if (ret & MP_STREAM_POLL_RD) {
|
||||
rwx_num[0] += 1;
|
||||
}
|
||||
if (ret & MP_STREAM_POLL_WR) {
|
||||
rwx_num[1] += 1;
|
||||
}
|
||||
if ((ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) {
|
||||
rwx_num[2] += 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)rwx_num;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return n_ready;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t poll_set_poll_until_ready_or_timeout(poll_set_t *poll_set, size_t *rwx_num, mp_uint_t timeout) {
|
||||
mp_uint_t start_ticks = mp_hal_ticks_ms();
|
||||
|
||||
#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
|
||||
|
||||
for (;;) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
|
||||
// Compute the timeout.
|
||||
int t = MICROPY_PY_SELECT_IOCTL_CALL_PERIOD_MS;
|
||||
if (poll_set_all_are_fds(poll_set)) {
|
||||
// All our pollables are file descriptors, so we can use a blocking
|
||||
// poll and let it (the underlying system) handle the timeout.
|
||||
if (timeout == (mp_uint_t)-1) {
|
||||
t = -1;
|
||||
} else {
|
||||
mp_uint_t delta = mp_hal_ticks_ms() - start_ticks;
|
||||
if (delta >= timeout) {
|
||||
t = 0;
|
||||
} else {
|
||||
t = timeout - delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call system poll for those objects that have a file descriptor.
|
||||
int n_ready = poll(poll_set->pollfds, poll_set->max_used, t);
|
||||
|
||||
MP_THREAD_GIL_ENTER();
|
||||
|
||||
// The call to poll() may have been interrupted, but per PEP 475 we must retry if the
|
||||
// signal is EINTR (this implements a special case of calling MP_HAL_RETRY_SYSCALL()).
|
||||
if (n_ready == -1) {
|
||||
int err = errno;
|
||||
if (err != EINTR) {
|
||||
mp_raise_OSError(err);
|
||||
}
|
||||
n_ready = 0;
|
||||
}
|
||||
|
||||
// Explicitly poll any objects that do not have a file descriptor.
|
||||
if (!poll_set_all_are_fds(poll_set)) {
|
||||
n_ready += poll_set_poll_once(poll_set, rwx_num);
|
||||
}
|
||||
|
||||
// Return if an object is ready, or if the timeout expired.
|
||||
if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_ticks >= timeout)) {
|
||||
return n_ready;
|
||||
}
|
||||
|
||||
// This would be MICROPY_EVENT_POLL_HOOK but the call to poll() above already includes a delay.
|
||||
mp_handle_pending(true);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
for (;;) {
|
||||
// poll the objects
|
||||
mp_uint_t n_ready = poll_set_poll_once(poll_set, rwx_num);
|
||||
if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_ticks >= timeout)) {
|
||||
return n_ready;
|
||||
}
|
||||
// CIRCUITPY
|
||||
RUN_BACKGROUND_TASKS;
|
||||
if (mp_hal_is_interrupted()) {
|
||||
return 0;
|
||||
}
|
||||
// end CIRCUITPY
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MICROPY_PY_SELECT_SELECT
|
||||
// select(rlist, wlist, xlist[, timeout])
|
||||
STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) {
|
||||
// get array data from tuple/list arguments
|
||||
size_t rwx_len[3];
|
||||
mp_obj_t *r_array, *w_array, *x_array;
|
||||
mp_obj_get_array(args[0], &rwx_len[0], &r_array);
|
||||
mp_obj_get_array(args[1], &rwx_len[1], &w_array);
|
||||
mp_obj_get_array(args[2], &rwx_len[2], &x_array);
|
||||
|
||||
// get timeout
|
||||
mp_uint_t timeout = -1;
|
||||
if (n_args == 4) {
|
||||
if (args[3] != mp_const_none) {
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
float timeout_f = mp_obj_get_float_to_f(args[3]);
|
||||
if (timeout_f >= 0) {
|
||||
timeout = (mp_uint_t)(timeout_f * 1000);
|
||||
}
|
||||
#else
|
||||
timeout = mp_obj_get_int(args[3]) * 1000;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// merge separate lists and get the ioctl function for each object
|
||||
poll_set_t poll_set;
|
||||
poll_set_init(&poll_set, rwx_len[0] + rwx_len[1] + rwx_len[2]);
|
||||
poll_set_add_obj(&poll_set, r_array, rwx_len[0], MP_STREAM_POLL_RD, true);
|
||||
poll_set_add_obj(&poll_set, w_array, rwx_len[1], MP_STREAM_POLL_WR, true);
|
||||
poll_set_add_obj(&poll_set, x_array, rwx_len[2], MP_STREAM_POLL_ERR | MP_STREAM_POLL_HUP, true);
|
||||
|
||||
// poll all objects
|
||||
rwx_len[0] = rwx_len[1] = rwx_len[2] = 0;
|
||||
poll_set_poll_until_ready_or_timeout(&poll_set, rwx_len, timeout);
|
||||
|
||||
// one or more objects are ready, or we had a timeout
|
||||
mp_obj_t list_array[3];
|
||||
list_array[0] = mp_obj_new_list(rwx_len[0], NULL);
|
||||
list_array[1] = mp_obj_new_list(rwx_len[1], NULL);
|
||||
list_array[2] = mp_obj_new_list(rwx_len[2], NULL);
|
||||
rwx_len[0] = rwx_len[1] = rwx_len[2] = 0;
|
||||
for (mp_uint_t i = 0; i < poll_set.map.alloc; ++i) {
|
||||
if (!mp_map_slot_is_filled(&poll_set.map, i)) {
|
||||
continue;
|
||||
}
|
||||
// CIRCUITPY
|
||||
RUN_BACKGROUND_TASKS;
|
||||
|
||||
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_set.map.table[i].value);
|
||||
if (poll_obj->revents & MP_STREAM_POLL_RD) {
|
||||
((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[0]))->items[rwx_len[0]++] = poll_obj->obj;
|
||||
}
|
||||
if (poll_obj->revents & MP_STREAM_POLL_WR) {
|
||||
((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[1]))->items[rwx_len[1]++] = poll_obj->obj;
|
||||
}
|
||||
if ((poll_obj->revents & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) {
|
||||
((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[2]))->items[rwx_len[2]++] = poll_obj->obj;
|
||||
}
|
||||
}
|
||||
poll_set_deinit(&poll_set);
|
||||
return mp_obj_new_tuple(3, list_array);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_select_obj, 3, 4, select_select);
|
||||
#endif // MICROPY_PY_SELECT_SELECT
|
||||
|
||||
typedef struct _mp_obj_poll_t {
|
||||
mp_obj_base_t base;
|
||||
poll_set_t poll_set;
|
||||
short iter_cnt;
|
||||
short iter_idx;
|
||||
int flags;
|
||||
// callee-owned tuple
|
||||
mp_obj_t ret_tuple;
|
||||
} mp_obj_poll_t;
|
||||
|
||||
// register(obj[, eventmask])
|
||||
STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
mp_uint_t events;
|
||||
if (n_args == 3) {
|
||||
events = mp_obj_get_int(args[2]);
|
||||
} else {
|
||||
events = MP_STREAM_POLL_RD | MP_STREAM_POLL_WR;
|
||||
}
|
||||
poll_set_add_obj(&self->poll_set, &args[1], 1, events, false);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register);
|
||||
|
||||
// unregister(obj)
|
||||
STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_map_elem_t *elem = mp_map_lookup(&self->poll_set.map, mp_obj_id(obj_in), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
|
||||
|
||||
#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
|
||||
if (elem != NULL) {
|
||||
poll_obj_t *poll_obj = (poll_obj_t *)MP_OBJ_TO_PTR(elem->value);
|
||||
if (poll_obj->pollfd != NULL) {
|
||||
poll_obj->pollfd->fd = -1;
|
||||
--self->poll_set.used;
|
||||
}
|
||||
elem->value = MP_OBJ_NULL;
|
||||
}
|
||||
#else
|
||||
(void)elem;
|
||||
#endif
|
||||
|
||||
// TODO raise KeyError if obj didn't exist in map
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister);
|
||||
|
||||
// modify(obj, eventmask)
|
||||
STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_map_elem_t *elem = mp_map_lookup(&self->poll_set.map, mp_obj_id(obj_in), MP_MAP_LOOKUP);
|
||||
if (elem == NULL) {
|
||||
mp_raise_OSError(MP_ENOENT);
|
||||
}
|
||||
poll_obj_set_events((poll_obj_t *)MP_OBJ_TO_PTR(elem->value), mp_obj_get_int(eventmask_in));
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify);
|
||||
|
||||
STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
// work out timeout (its given already in ms)
|
||||
mp_uint_t timeout = -1;
|
||||
int flags = 0;
|
||||
if (n_args >= 2) {
|
||||
if (args[1] != mp_const_none) {
|
||||
mp_int_t timeout_i = mp_obj_get_int(args[1]);
|
||||
if (timeout_i >= 0) {
|
||||
timeout = timeout_i;
|
||||
}
|
||||
}
|
||||
if (n_args >= 3) {
|
||||
flags = mp_obj_get_int(args[2]);
|
||||
}
|
||||
}
|
||||
|
||||
self->flags = flags;
|
||||
|
||||
return poll_set_poll_until_ready_or_timeout(&self->poll_set, NULL, timeout);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
mp_uint_t n_ready = poll_poll_internal(n_args, args);
|
||||
|
||||
// one or more objects are ready, or we had a timeout
|
||||
mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL));
|
||||
n_ready = 0;
|
||||
for (mp_uint_t i = 0; i < self->poll_set.map.alloc; ++i) {
|
||||
if (!mp_map_slot_is_filled(&self->poll_set.map, i)) {
|
||||
continue;
|
||||
}
|
||||
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_set.map.table[i].value);
|
||||
if (poll_obj_get_revents(poll_obj) != 0) {
|
||||
mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj_get_revents(poll_obj))};
|
||||
ret_list->items[n_ready++] = mp_obj_new_tuple(2, tuple);
|
||||
}
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(ret_list);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 2, poll_poll);
|
||||
|
||||
STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
if (self->ret_tuple == MP_OBJ_NULL) {
|
||||
self->ret_tuple = mp_obj_new_tuple(2, NULL);
|
||||
}
|
||||
|
||||
int n_ready = poll_poll_internal(n_args, args);
|
||||
self->iter_cnt = n_ready;
|
||||
self->iter_idx = 0;
|
||||
|
||||
return args[0];
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_ipoll_obj, 1, 3, poll_ipoll);
|
||||
|
||||
STATIC mp_obj_t poll_iternext(mp_obj_t self_in) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
if (self->iter_cnt == 0) {
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
}
|
||||
|
||||
self->iter_cnt--;
|
||||
|
||||
for (mp_uint_t i = self->iter_idx; i < self->poll_set.map.alloc; ++i) {
|
||||
self->iter_idx++;
|
||||
if (!mp_map_slot_is_filled(&self->poll_set.map, i)) {
|
||||
continue;
|
||||
}
|
||||
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_set.map.table[i].value);
|
||||
if (poll_obj_get_revents(poll_obj) != 0) {
|
||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple);
|
||||
t->items[0] = poll_obj->obj;
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(poll_obj_get_revents(poll_obj));
|
||||
if (self->flags & FLAG_ONESHOT) {
|
||||
// Don't poll next time, until new event mask will be set explicitly
|
||||
poll_obj_set_events(poll_obj, 0);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(t);
|
||||
}
|
||||
}
|
||||
|
||||
assert(!"inconsistent number of poll active entries");
|
||||
self->iter_cnt = 0;
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
}
|
||||
|
||||
STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ipoll), MP_ROM_PTR(&poll_ipoll_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table);
|
||||
|
||||
STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
mp_type_poll,
|
||||
MP_QSTR_poll,
|
||||
MP_TYPE_FLAG_ITER_IS_ITERNEXT,
|
||||
iter, poll_iternext,
|
||||
locals_dict, &poll_locals_dict
|
||||
);
|
||||
|
||||
// poll()
|
||||
STATIC mp_obj_t select_poll(void) {
|
||||
mp_obj_poll_t *poll = mp_obj_malloc(mp_obj_poll_t, &mp_type_poll);
|
||||
poll_set_init(&poll->poll_set, 0);
|
||||
poll->iter_cnt = 0;
|
||||
poll->ret_tuple = MP_OBJ_NULL;
|
||||
return MP_OBJ_FROM_PTR(poll);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_select_poll_obj, select_poll);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_select_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_select) },
|
||||
#if MICROPY_PY_SELECT_SELECT
|
||||
{ MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_select_select_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mp_select_poll_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_POLLIN), MP_ROM_INT(MP_STREAM_POLL_RD) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_POLLOUT), MP_ROM_INT(MP_STREAM_POLL_WR) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_POLLERR), MP_ROM_INT(MP_STREAM_POLL_ERR) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_POLLHUP), MP_ROM_INT(MP_STREAM_POLL_HUP) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_select = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_select_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_select, mp_module_select);
|
||||
|
||||
#endif // MICROPY_PY_SELECT
|
236
extmod/modtime.c
Normal file
236
extmod/modtime.c
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2023 Damien P. George
|
||||
* Copyright (c) 2016 Paul Sokolovsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "py/mphal.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/smallint.h"
|
||||
#include "extmod/modtime.h"
|
||||
|
||||
#if MICROPY_PY_TIME
|
||||
|
||||
#ifdef MICROPY_PY_TIME_INCLUDEFILE
|
||||
#include MICROPY_PY_TIME_INCLUDEFILE
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME
|
||||
|
||||
#include "shared/timeutils/timeutils.h"
|
||||
|
||||
// localtime([secs])
|
||||
// Convert a time expressed in seconds since the Epoch into an 8-tuple which
|
||||
// contains: (year, month, mday, hour, minute, second, weekday, yearday)
|
||||
// If secs is not provided or None, then the current time is used.
|
||||
// - year is the full year, eg 2000
|
||||
// - month is 1-12
|
||||
// - mday is 1-31
|
||||
// - hour is 0-23
|
||||
// - minute is 0-59
|
||||
// - second is 0-59
|
||||
// - weekday is 0-6 for Mon-Sun
|
||||
// - yearday is 1-366
|
||||
STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0 || args[0] == mp_const_none) {
|
||||
// Get current date and time.
|
||||
return mp_time_localtime_get();
|
||||
} else {
|
||||
// Convert given seconds to tuple.
|
||||
mp_int_t seconds = mp_obj_get_int(args[0]);
|
||||
timeutils_struct_time_t tm;
|
||||
timeutils_seconds_since_epoch_to_struct_time(seconds, &tm);
|
||||
mp_obj_t tuple[8] = {
|
||||
tuple[0] = mp_obj_new_int(tm.tm_year),
|
||||
tuple[1] = mp_obj_new_int(tm.tm_mon),
|
||||
tuple[2] = mp_obj_new_int(tm.tm_mday),
|
||||
tuple[3] = mp_obj_new_int(tm.tm_hour),
|
||||
tuple[4] = mp_obj_new_int(tm.tm_min),
|
||||
tuple[5] = mp_obj_new_int(tm.tm_sec),
|
||||
tuple[6] = mp_obj_new_int(tm.tm_wday),
|
||||
tuple[7] = mp_obj_new_int(tm.tm_yday),
|
||||
};
|
||||
return mp_obj_new_tuple(8, tuple);
|
||||
}
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_time_localtime_obj, 0, 1, time_localtime);
|
||||
|
||||
// mktime()
|
||||
// This is the inverse function of localtime. Its argument is a full 8-tuple
|
||||
// which expresses a time as per localtime. It returns an integer which is
|
||||
// the number of seconds since the Epoch (eg 1st Jan 1970, or 1st Jan 2000).
|
||||
STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
|
||||
size_t len;
|
||||
mp_obj_t *elem;
|
||||
mp_obj_get_array(tuple, &len, &elem);
|
||||
|
||||
// localtime generates a tuple of len 8. CPython uses 9, so we accept both.
|
||||
if (len < 8 || len > 9) {
|
||||
mp_raise_TypeError(MP_ERROR_TEXT("mktime needs a tuple of length 8 or 9"));
|
||||
}
|
||||
|
||||
return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]),
|
||||
mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]),
|
||||
mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5])));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_time_mktime_obj, time_mktime);
|
||||
|
||||
#endif // MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME
|
||||
|
||||
#if MICROPY_PY_TIME_TIME_TIME_NS
|
||||
|
||||
// time()
|
||||
// Return the number of seconds since the Epoch.
|
||||
STATIC mp_obj_t time_time(void) {
|
||||
return mp_time_time_get();
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_time_time_obj, time_time);
|
||||
|
||||
// time_ns()
|
||||
// Returns the number of nanoseconds since the Epoch, as an integer.
|
||||
STATIC mp_obj_t time_time_ns(void) {
|
||||
return mp_obj_new_int_from_ull(mp_hal_time_ns());
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_time_time_ns_obj, time_time_ns);
|
||||
|
||||
#endif // MICROPY_PY_TIME_TIME_TIME_NS
|
||||
|
||||
STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
|
||||
#ifdef MICROPY_PY_TIME_CUSTOM_SLEEP
|
||||
mp_time_sleep(seconds_o);
|
||||
#else
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_hal_delay_ms((mp_uint_t)(1000 * mp_obj_get_float(seconds_o)));
|
||||
#else
|
||||
mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o));
|
||||
#endif
|
||||
#endif
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_time_sleep_obj, time_sleep);
|
||||
|
||||
STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) {
|
||||
mp_int_t ms = mp_obj_get_int(arg);
|
||||
if (ms >= 0) {
|
||||
mp_hal_delay_ms(ms);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_time_sleep_ms_obj, time_sleep_ms);
|
||||
|
||||
STATIC mp_obj_t time_sleep_us(mp_obj_t arg) {
|
||||
mp_int_t us = mp_obj_get_int(arg);
|
||||
if (us > 0) {
|
||||
mp_hal_delay_us(us);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_time_sleep_us_obj, time_sleep_us);
|
||||
|
||||
STATIC mp_obj_t time_ticks_ms(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_TIME_TICKS_PERIOD - 1));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_time_ticks_ms_obj, time_ticks_ms);
|
||||
|
||||
STATIC mp_obj_t time_ticks_us(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_us() & (MICROPY_PY_TIME_TICKS_PERIOD - 1));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_time_ticks_us_obj, time_ticks_us);
|
||||
|
||||
STATIC mp_obj_t time_ticks_cpu(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & (MICROPY_PY_TIME_TICKS_PERIOD - 1));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_time_ticks_cpu_obj, time_ticks_cpu);
|
||||
|
||||
STATIC mp_obj_t time_ticks_diff(mp_obj_t end_in, mp_obj_t start_in) {
|
||||
// we assume that the arguments come from ticks_xx so are small ints
|
||||
mp_uint_t start = MP_OBJ_SMALL_INT_VALUE(start_in);
|
||||
mp_uint_t end = MP_OBJ_SMALL_INT_VALUE(end_in);
|
||||
// Optimized formula avoiding if conditions. We adjust difference "forward",
|
||||
// wrap it around and adjust back.
|
||||
mp_int_t diff = ((end - start + MICROPY_PY_TIME_TICKS_PERIOD / 2) & (MICROPY_PY_TIME_TICKS_PERIOD - 1))
|
||||
- MICROPY_PY_TIME_TICKS_PERIOD / 2;
|
||||
return MP_OBJ_NEW_SMALL_INT(diff);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_time_ticks_diff_obj, time_ticks_diff);
|
||||
|
||||
STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) {
|
||||
// we assume that first argument come from ticks_xx so is small int
|
||||
mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_in);
|
||||
mp_uint_t delta = mp_obj_get_int(delta_in);
|
||||
|
||||
// Check that delta does not overflow the range that ticks_diff can handle.
|
||||
// This ensures the following:
|
||||
// - ticks_diff(ticks_add(T, delta), T) == delta
|
||||
// - ticks_diff(T, ticks_add(T, delta)) == -delta
|
||||
// The latter requires excluding delta=-TICKS_PERIOD/2.
|
||||
//
|
||||
// This unsigned comparison is equivalent to a signed comparison of:
|
||||
// delta <= -TICKS_PERIOD/2 || delta >= TICKS_PERIOD/2
|
||||
if (delta + MICROPY_PY_TIME_TICKS_PERIOD / 2 - 1 >= MICROPY_PY_TIME_TICKS_PERIOD - 1) {
|
||||
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("ticks interval overflow"));
|
||||
}
|
||||
|
||||
return MP_OBJ_NEW_SMALL_INT((ticks + delta) & (MICROPY_PY_TIME_TICKS_PERIOD - 1));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_time_ticks_add_obj, time_ticks_add);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_time) },
|
||||
|
||||
#if MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME
|
||||
{ MP_ROM_QSTR(MP_QSTR_gmtime), MP_ROM_PTR(&mp_time_localtime_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&mp_time_localtime_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&mp_time_mktime_obj) },
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_TIME_TIME_TIME_NS
|
||||
{ MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_time_time_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_time_ns), MP_ROM_PTR(&mp_time_time_ns_obj) },
|
||||
#endif
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_time_sleep_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_time_sleep_ms_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_time_sleep_us_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_time_ticks_ms_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_time_ticks_us_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_time_ticks_cpu_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_time_ticks_add_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_time_ticks_diff_obj) },
|
||||
|
||||
#ifdef MICROPY_PY_TIME_EXTRA_GLOBALS
|
||||
MICROPY_PY_TIME_EXTRA_GLOBALS
|
||||
#endif
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_time_globals, mp_module_time_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_time = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_time_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_time, mp_module_time);
|
||||
|
||||
#endif // MICROPY_PY_TIME
|
@ -24,19 +24,20 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MODUTIME_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MODUTIME_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_us_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_ms_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_us_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_cpu_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_time_ns_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_time_mktime_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_time_sleep_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_time_sleep_ms_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_time_sleep_us_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_time_ticks_ms_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_time_ticks_us_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_time_ticks_cpu_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_time_ticks_diff_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_time_ticks_add_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_time_time_ns_obj);
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MODUTIME_H
|
@ -582,7 +582,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob
|
||||
STATIC mp_obj_t uctypes_struct_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
|
||||
mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_INT:
|
||||
case MP_UNARY_OP_INT_MAYBE:
|
||||
if (mp_obj_is_type(self->desc, &mp_type_tuple)) {
|
||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc);
|
||||
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
|
||||
@ -718,6 +718,8 @@ const mp_obj_module_t mp_module_uctypes = {
|
||||
.globals = (mp_obj_dict_t *)&mp_module_uctypes_globals,
|
||||
};
|
||||
|
||||
// uctypes is not a Python standard library module (hence "uctypes"
|
||||
// not "ctypes") and therefore shouldn't be extensible.
|
||||
MP_REGISTER_MODULE(MP_QSTR_uctypes, mp_module_uctypes);
|
||||
|
||||
#endif
|
||||
|
@ -1,384 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Damien P. George
|
||||
* Copyright (c) 2015-2017 Paul Sokolovsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#if MICROPY_PY_USELECT
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/objlist.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/mphal.h"
|
||||
#include "shared/runtime/interrupt_char.h"
|
||||
|
||||
// Flags for poll()
|
||||
#define FLAG_ONESHOT (1)
|
||||
|
||||
typedef struct _poll_obj_t {
|
||||
mp_obj_t obj;
|
||||
mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
|
||||
mp_uint_t flags;
|
||||
mp_uint_t flags_ret;
|
||||
} poll_obj_t;
|
||||
|
||||
STATIC void poll_map_add(mp_map_t *poll_map, const mp_obj_t *obj, mp_uint_t obj_len, mp_uint_t flags, bool or_flags) {
|
||||
for (mp_uint_t i = 0; i < obj_len; i++) {
|
||||
mp_map_elem_t *elem = mp_map_lookup(poll_map, mp_obj_id(obj[i]), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
|
||||
if (elem->value == MP_OBJ_NULL) {
|
||||
// object not found; get its ioctl and add it to the poll list
|
||||
const mp_stream_p_t *stream_p = mp_get_stream_raise(obj[i], MP_STREAM_OP_IOCTL);
|
||||
poll_obj_t *poll_obj = m_new_obj(poll_obj_t);
|
||||
poll_obj->obj = obj[i];
|
||||
poll_obj->ioctl = stream_p->ioctl;
|
||||
poll_obj->flags = flags;
|
||||
poll_obj->flags_ret = 0;
|
||||
elem->value = MP_OBJ_FROM_PTR(poll_obj);
|
||||
} else {
|
||||
// object exists; update its flags
|
||||
if (or_flags) {
|
||||
((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags |= flags;
|
||||
} else {
|
||||
((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// poll each object in the map
|
||||
STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, size_t *rwx_num) {
|
||||
mp_uint_t n_ready = 0;
|
||||
for (mp_uint_t i = 0; i < poll_map->alloc; ++i) {
|
||||
if (!mp_map_slot_is_filled(poll_map, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map->table[i].value);
|
||||
int errcode;
|
||||
mp_int_t ret = poll_obj->ioctl(poll_obj->obj, MP_STREAM_POLL, poll_obj->flags, &errcode);
|
||||
poll_obj->flags_ret = ret;
|
||||
|
||||
if (ret == -1) {
|
||||
// error doing ioctl
|
||||
mp_raise_OSError(errcode);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
// object is ready
|
||||
n_ready += 1;
|
||||
if (rwx_num != NULL) {
|
||||
if (ret & MP_STREAM_POLL_RD) {
|
||||
rwx_num[0] += 1;
|
||||
}
|
||||
if (ret & MP_STREAM_POLL_WR) {
|
||||
rwx_num[1] += 1;
|
||||
}
|
||||
if ((ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) {
|
||||
rwx_num[2] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return n_ready;
|
||||
}
|
||||
|
||||
#if MICROPY_PY_USELECT_SELECT
|
||||
// select(rlist, wlist, xlist[, timeout])
|
||||
STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) {
|
||||
// get array data from tuple/list arguments
|
||||
size_t rwx_len[3];
|
||||
mp_obj_t *r_array, *w_array, *x_array;
|
||||
mp_obj_get_array(args[0], &rwx_len[0], &r_array);
|
||||
mp_obj_get_array(args[1], &rwx_len[1], &w_array);
|
||||
mp_obj_get_array(args[2], &rwx_len[2], &x_array);
|
||||
|
||||
// get timeout
|
||||
mp_uint_t timeout = -1;
|
||||
if (n_args == 4) {
|
||||
if (args[3] != mp_const_none) {
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
float timeout_f = mp_obj_get_float_to_f(args[3]);
|
||||
if (timeout_f >= 0) {
|
||||
timeout = (mp_uint_t)(timeout_f * 1000);
|
||||
}
|
||||
#else
|
||||
timeout = mp_obj_get_int(args[3]) * 1000;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// merge separate lists and get the ioctl function for each object
|
||||
mp_map_t poll_map;
|
||||
mp_map_init(&poll_map, rwx_len[0] + rwx_len[1] + rwx_len[2]);
|
||||
poll_map_add(&poll_map, r_array, rwx_len[0], MP_STREAM_POLL_RD, true);
|
||||
poll_map_add(&poll_map, w_array, rwx_len[1], MP_STREAM_POLL_WR, true);
|
||||
poll_map_add(&poll_map, x_array, rwx_len[2], MP_STREAM_POLL_ERR | MP_STREAM_POLL_HUP, true);
|
||||
|
||||
mp_uint_t start_tick = mp_hal_ticks_ms();
|
||||
rwx_len[0] = rwx_len[1] = rwx_len[2] = 0;
|
||||
for (;;) {
|
||||
// poll the objects
|
||||
mp_uint_t n_ready = poll_map_poll(&poll_map, rwx_len);
|
||||
|
||||
if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_tick >= timeout)) {
|
||||
// one or more objects are ready, or we had a timeout
|
||||
mp_obj_t list_array[3];
|
||||
list_array[0] = mp_obj_new_list(rwx_len[0], NULL);
|
||||
list_array[1] = mp_obj_new_list(rwx_len[1], NULL);
|
||||
list_array[2] = mp_obj_new_list(rwx_len[2], NULL);
|
||||
rwx_len[0] = rwx_len[1] = rwx_len[2] = 0;
|
||||
for (mp_uint_t i = 0; i < poll_map.alloc; ++i) {
|
||||
if (!mp_map_slot_is_filled(&poll_map, i)) {
|
||||
continue;
|
||||
}
|
||||
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map.table[i].value);
|
||||
if (poll_obj->flags_ret & MP_STREAM_POLL_RD) {
|
||||
((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[0]))->items[rwx_len[0]++] = poll_obj->obj;
|
||||
}
|
||||
if (poll_obj->flags_ret & MP_STREAM_POLL_WR) {
|
||||
((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[1]))->items[rwx_len[1]++] = poll_obj->obj;
|
||||
}
|
||||
if ((poll_obj->flags_ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) {
|
||||
((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[2]))->items[rwx_len[2]++] = poll_obj->obj;
|
||||
}
|
||||
}
|
||||
mp_map_deinit(&poll_map);
|
||||
return mp_obj_new_tuple(3, list_array);
|
||||
}
|
||||
// CIRCUITPY
|
||||
RUN_BACKGROUND_TASKS;
|
||||
}
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_select_obj, 3, 4, select_select);
|
||||
#endif // MICROPY_PY_USELECT_SELECT
|
||||
|
||||
typedef struct _mp_obj_poll_t {
|
||||
mp_obj_base_t base;
|
||||
mp_map_t poll_map;
|
||||
short iter_cnt;
|
||||
short iter_idx;
|
||||
int flags;
|
||||
// callee-owned tuple
|
||||
mp_obj_t ret_tuple;
|
||||
} mp_obj_poll_t;
|
||||
|
||||
// register(obj[, eventmask])
|
||||
STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
mp_uint_t flags;
|
||||
if (n_args == 3) {
|
||||
flags = mp_obj_get_int(args[2]);
|
||||
} else {
|
||||
flags = MP_STREAM_POLL_RD | MP_STREAM_POLL_WR;
|
||||
}
|
||||
poll_map_add(&self->poll_map, &args[1], 1, flags, false);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register);
|
||||
|
||||
// unregister(obj)
|
||||
STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
|
||||
// TODO raise KeyError if obj didn't exist in map
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister);
|
||||
|
||||
// modify(obj, eventmask)
|
||||
STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_map_elem_t *elem = mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP);
|
||||
if (elem == NULL) {
|
||||
mp_raise_OSError(MP_ENOENT);
|
||||
}
|
||||
((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = mp_obj_get_int(eventmask_in);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify);
|
||||
|
||||
STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
// work out timeout (its given already in ms)
|
||||
mp_uint_t timeout = -1;
|
||||
int flags = 0;
|
||||
if (n_args >= 2) {
|
||||
if (args[1] != mp_const_none) {
|
||||
mp_int_t timeout_i = mp_obj_get_int(args[1]);
|
||||
if (timeout_i >= 0) {
|
||||
timeout = timeout_i;
|
||||
}
|
||||
}
|
||||
if (n_args >= 3) {
|
||||
flags = mp_obj_get_int(args[2]);
|
||||
}
|
||||
}
|
||||
|
||||
self->flags = flags;
|
||||
|
||||
mp_uint_t start_tick = mp_hal_ticks_ms();
|
||||
mp_uint_t n_ready;
|
||||
for (;;) {
|
||||
// poll the objects
|
||||
n_ready = poll_map_poll(&self->poll_map, NULL);
|
||||
if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_tick >= timeout)) {
|
||||
break;
|
||||
}
|
||||
// CIRCUITPY
|
||||
RUN_BACKGROUND_TASKS;
|
||||
if (mp_hal_is_interrupted()) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return n_ready;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
mp_uint_t n_ready = poll_poll_internal(n_args, args);
|
||||
|
||||
// one or more objects are ready, or we had a timeout
|
||||
mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL));
|
||||
n_ready = 0;
|
||||
for (mp_uint_t i = 0; i < self->poll_map.alloc; ++i) {
|
||||
if (!mp_map_slot_is_filled(&self->poll_map, i)) {
|
||||
continue;
|
||||
}
|
||||
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value);
|
||||
if (poll_obj->flags_ret != 0) {
|
||||
mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret)};
|
||||
ret_list->items[n_ready++] = mp_obj_new_tuple(2, tuple);
|
||||
if (self->flags & FLAG_ONESHOT) {
|
||||
// Don't poll next time, until new event flags will be set explicitly
|
||||
poll_obj->flags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(ret_list);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll);
|
||||
|
||||
STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
if (self->ret_tuple == MP_OBJ_NULL) {
|
||||
self->ret_tuple = mp_obj_new_tuple(2, NULL);
|
||||
}
|
||||
|
||||
int n_ready = poll_poll_internal(n_args, args);
|
||||
self->iter_cnt = n_ready;
|
||||
self->iter_idx = 0;
|
||||
|
||||
return args[0];
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_ipoll_obj, 1, 3, poll_ipoll);
|
||||
|
||||
STATIC mp_obj_t poll_iternext(mp_obj_t self_in) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
if (self->iter_cnt == 0) {
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
}
|
||||
|
||||
self->iter_cnt--;
|
||||
|
||||
for (mp_uint_t i = self->iter_idx; i < self->poll_map.alloc; ++i) {
|
||||
self->iter_idx++;
|
||||
if (!mp_map_slot_is_filled(&self->poll_map, i)) {
|
||||
continue;
|
||||
}
|
||||
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value);
|
||||
if (poll_obj->flags_ret != 0) {
|
||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple);
|
||||
t->items[0] = poll_obj->obj;
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret);
|
||||
if (self->flags & FLAG_ONESHOT) {
|
||||
// Don't poll next time, until new event flags will be set explicitly
|
||||
poll_obj->flags = 0;
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(t);
|
||||
}
|
||||
}
|
||||
|
||||
assert(!"inconsistent number of poll active entries");
|
||||
self->iter_cnt = 0;
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
}
|
||||
|
||||
STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ipoll), MP_ROM_PTR(&poll_ipoll_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table);
|
||||
|
||||
STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
mp_type_poll,
|
||||
MP_QSTR_poll,
|
||||
MP_TYPE_FLAG_ITER_IS_ITERNEXT,
|
||||
iter, poll_iternext,
|
||||
locals_dict, &poll_locals_dict
|
||||
);
|
||||
|
||||
// poll()
|
||||
STATIC mp_obj_t select_poll(void) {
|
||||
mp_obj_poll_t *poll = mp_obj_malloc(mp_obj_poll_t, &mp_type_poll);
|
||||
mp_map_init(&poll->poll_map, 0);
|
||||
poll->iter_cnt = 0;
|
||||
poll->ret_tuple = MP_OBJ_NULL;
|
||||
return MP_OBJ_FROM_PTR(poll);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_select_poll_obj, select_poll);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_select_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uselect) },
|
||||
#if MICROPY_PY_USELECT_SELECT
|
||||
{ MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_select_select_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mp_select_poll_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_POLLIN), MP_ROM_INT(MP_STREAM_POLL_RD) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_POLLOUT), MP_ROM_INT(MP_STREAM_POLL_WR) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_POLLERR), MP_ROM_INT(MP_STREAM_POLL_ERR) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_POLLHUP), MP_ROM_INT(MP_STREAM_POLL_HUP) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uselect = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_select_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_select, mp_module_uselect);
|
||||
|
||||
#endif // MICROPY_PY_USELECT
|
@ -1,121 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2016 Damien P. George
|
||||
* Copyright (c) 2016 Paul Sokolovsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#if MICROPY_PY_UTIME_MP_HAL
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/smallint.h"
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/utime_mphal.h"
|
||||
|
||||
STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_hal_delay_ms((mp_uint_t)(1000 * mp_obj_get_float(seconds_o)));
|
||||
#else
|
||||
mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o));
|
||||
#endif
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_obj, time_sleep);
|
||||
|
||||
STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) {
|
||||
mp_int_t ms = mp_obj_get_int(arg);
|
||||
if (ms >= 0) {
|
||||
mp_hal_delay_ms(ms);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj, time_sleep_ms);
|
||||
|
||||
STATIC mp_obj_t time_sleep_us(mp_obj_t arg) {
|
||||
mp_int_t us = mp_obj_get_int(arg);
|
||||
if (us > 0) {
|
||||
mp_hal_delay_us(us);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_us_obj, time_sleep_us);
|
||||
|
||||
STATIC mp_obj_t time_ticks_ms(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_ms_obj, time_ticks_ms);
|
||||
|
||||
STATIC mp_obj_t time_ticks_us(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_us() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_us_obj, time_ticks_us);
|
||||
|
||||
STATIC mp_obj_t time_ticks_cpu(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_cpu_obj, time_ticks_cpu);
|
||||
|
||||
STATIC mp_obj_t time_ticks_diff(mp_obj_t end_in, mp_obj_t start_in) {
|
||||
// we assume that the arguments come from ticks_xx so are small ints
|
||||
mp_uint_t start = MP_OBJ_SMALL_INT_VALUE(start_in);
|
||||
mp_uint_t end = MP_OBJ_SMALL_INT_VALUE(end_in);
|
||||
// Optimized formula avoiding if conditions. We adjust difference "forward",
|
||||
// wrap it around and adjust back.
|
||||
mp_int_t diff = ((end - start + MICROPY_PY_UTIME_TICKS_PERIOD / 2) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1))
|
||||
- MICROPY_PY_UTIME_TICKS_PERIOD / 2;
|
||||
return MP_OBJ_NEW_SMALL_INT(diff);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj, time_ticks_diff);
|
||||
|
||||
STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) {
|
||||
// we assume that first argument come from ticks_xx so is small int
|
||||
mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_in);
|
||||
mp_uint_t delta = mp_obj_get_int(delta_in);
|
||||
|
||||
// Check that delta does not overflow the range that ticks_diff can handle.
|
||||
// This ensures the following:
|
||||
// - ticks_diff(ticks_add(T, delta), T) == delta
|
||||
// - ticks_diff(T, ticks_add(T, delta)) == -delta
|
||||
// The latter requires excluding delta=-TICKS_PERIOD/2.
|
||||
//
|
||||
// This unsigned comparison is equivalent to a signed comparison of:
|
||||
// delta <= -TICKS_PERIOD/2 || delta >= TICKS_PERIOD/2
|
||||
if (delta + MICROPY_PY_UTIME_TICKS_PERIOD / 2 - 1 >= MICROPY_PY_UTIME_TICKS_PERIOD - 1) {
|
||||
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("ticks interval overflow"));
|
||||
}
|
||||
|
||||
return MP_OBJ_NEW_SMALL_INT((ticks + delta) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj, time_ticks_add);
|
||||
|
||||
// Returns the number of nanoseconds since the Epoch, as an integer.
|
||||
STATIC mp_obj_t time_time_ns(void) {
|
||||
return mp_obj_new_int_from_ull(mp_hal_time_ns());
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_time_ns_obj, time_time_ns);
|
||||
|
||||
#endif // MICROPY_PY_UTIME_MP_HAL
|
@ -93,13 +93,6 @@ STATIC mp_uint_t file_obj_write(mp_obj_t self_in, const void *buf, mp_uint_t siz
|
||||
return sz_out;
|
||||
}
|
||||
|
||||
|
||||
STATIC mp_obj_t file_obj___exit__(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
return mp_stream_close(args[0]);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(file_obj___exit___obj, 4, 4, file_obj___exit__);
|
||||
|
||||
STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
pyb_file_obj_t *self = MP_OBJ_TO_PTR(o_in);
|
||||
|
||||
@ -162,9 +155,8 @@ STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&mp_stream___exit___obj) },
|
||||
};
|
||||
#define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args)
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table);
|
||||
|
||||
|
@ -323,7 +323,7 @@ STATIC mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) {
|
||||
size_t from = 1;
|
||||
char *cwd = vstr_str(&self->cur_dir);
|
||||
while (from < CWD_LEN) {
|
||||
for (; cwd[from] == '/' && from < CWD_LEN; ++from) {
|
||||
for (; from < CWD_LEN && cwd[from] == '/'; ++from) {
|
||||
// Scan for the start
|
||||
}
|
||||
if (from > to) {
|
||||
@ -331,7 +331,7 @@ STATIC mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) {
|
||||
vstr_cut_out_bytes(&self->cur_dir, to, from - to);
|
||||
from = to;
|
||||
}
|
||||
for (; cwd[from] != '/' && from < CWD_LEN; ++from) {
|
||||
for (; from < CWD_LEN && cwd[from] != '/'; ++from) {
|
||||
// Scan for the next /
|
||||
}
|
||||
if ((from - to) == 1 && cwd[to] == '.') {
|
||||
|
@ -123,12 +123,6 @@ mp_obj_t MP_VFS_LFSx(file_open)(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mod
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t MP_VFS_LFSx(file___exit__)(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
return mp_stream_close(args[0]);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(MP_VFS_LFSx(file___exit___obj), 4, 4, MP_VFS_LFSx(file___exit__));
|
||||
|
||||
STATIC mp_uint_t MP_VFS_LFSx(file_read)(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
MP_OBJ_VFS_LFSx_FILE *self = MP_OBJ_TO_PTR(self_in);
|
||||
MP_VFS_LFSx(check_open)(self);
|
||||
@ -213,7 +207,7 @@ STATIC const mp_rom_map_elem_t MP_VFS_LFSx(file_locals_dict_table)[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&MP_VFS_LFSx(file___exit___obj)) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&mp_stream___exit___obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(MP_VFS_LFSx(file_locals_dict), MP_VFS_LFSx(file_locals_dict_table));
|
||||
|
||||
|
@ -332,7 +332,7 @@ STATIC mp_obj_t vfs_posix_stat(mp_obj_t self_in, mp_obj_t path_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_stat_obj, vfs_posix_stat);
|
||||
|
||||
#if MICROPY_PY_UOS_STATVFS
|
||||
#if MICROPY_PY_OS_STATVFS
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#define USE_STATFS 1
|
||||
@ -390,7 +390,7 @@ STATIC const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&vfs_posix_rename_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&vfs_posix_rmdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&vfs_posix_stat_obj) },
|
||||
#if MICROPY_PY_UOS_STATVFS
|
||||
#if MICROPY_PY_OS_STATVFS
|
||||
{ MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&vfs_posix_statvfs_obj) },
|
||||
#endif
|
||||
};
|
||||
|
@ -115,12 +115,6 @@ STATIC mp_obj_t vfs_posix_file_fileno(mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_file_fileno_obj, vfs_posix_file_fileno);
|
||||
|
||||
STATIC mp_obj_t vfs_posix_file___exit__(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
return mp_stream_close(args[0]);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vfs_posix_file___exit___obj, 4, 4, vfs_posix_file___exit__);
|
||||
|
||||
STATIC mp_uint_t vfs_posix_file_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_vfs_posix_file_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
check_fd_is_open(o);
|
||||
@ -159,12 +153,20 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_
|
||||
switch (request) {
|
||||
case MP_STREAM_FLUSH: {
|
||||
int ret;
|
||||
// fsync(stdin/stdout/stderr) may fail with EINVAL (or ENOTSUP on macos or EBADF
|
||||
// on windows), because the OS doesn't buffer these except for instance when they
|
||||
// are redirected from/to file, but don't propagate that error out. Because data
|
||||
// is not buffered by us, and stdin/out/err.flush() should just be a no-op.
|
||||
#if defined(__APPLE__)
|
||||
#define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == ENOTSUP)
|
||||
#elif defined(_MSC_VER)
|
||||
#define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == EBADF)
|
||||
#else
|
||||
#define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL)
|
||||
#endif
|
||||
MP_HAL_RETRY_SYSCALL(ret, fsync(o->fd), {
|
||||
if (err == EINVAL
|
||||
if (VFS_POSIX_STREAM_STDIO_ERR_CATCH
|
||||
&& (o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO)) {
|
||||
// fsync(stdin/stdout/stderr) may fail with EINVAL, but don't propagate that
|
||||
// error out. Because data is not buffered by us, and stdin/out/err.flush()
|
||||
// should just be a no-op.
|
||||
return 0;
|
||||
}
|
||||
*errcode = err;
|
||||
@ -194,7 +196,7 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_
|
||||
return 0;
|
||||
case MP_STREAM_GET_FILENO:
|
||||
return o->fd;
|
||||
#if MICROPY_PY_USELECT
|
||||
#if MICROPY_PY_SELECT && !MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
|
||||
case MP_STREAM_POLL: {
|
||||
#ifdef _WIN32
|
||||
mp_raise_NotImplementedError(MP_ERROR_TEXT("poll on file not available on win32"));
|
||||
@ -215,6 +217,15 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_
|
||||
if (pfd.revents & POLLOUT) {
|
||||
ret |= MP_STREAM_POLL_WR;
|
||||
}
|
||||
if (pfd.revents & POLLERR) {
|
||||
ret |= MP_STREAM_POLL_ERR;
|
||||
}
|
||||
if (pfd.revents & POLLHUP) {
|
||||
ret |= MP_STREAM_POLL_HUP;
|
||||
}
|
||||
if (pfd.revents & POLLNVAL) {
|
||||
ret |= MP_STREAM_POLL_NVAL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
@ -239,7 +250,7 @@ STATIC const mp_rom_map_elem_t vfs_posix_rawfile_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&vfs_posix_file___exit___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&mp_stream___exit___obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(vfs_posix_rawfile_locals_dict, vfs_posix_rawfile_locals_dict_table);
|
||||
@ -266,12 +277,58 @@ STATIC const mp_stream_p_t vfs_posix_textio_stream_p = {
|
||||
.is_text = true,
|
||||
};
|
||||
|
||||
#if MICROPY_PY_SYS_STDIO_BUFFER
|
||||
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stdin_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDIN_FILENO};
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stdout_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDOUT_FILENO};
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stderr_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDERR_FILENO};
|
||||
|
||||
// Forward declarations.
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stdin_obj;
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stdout_obj;
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stderr_obj;
|
||||
|
||||
STATIC void vfs_posix_textio_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
if (dest[0] != MP_OBJ_NULL) {
|
||||
// These objects are read-only.
|
||||
return;
|
||||
}
|
||||
|
||||
if (attr == MP_QSTR_buffer) {
|
||||
// Implement the `buffer` attribute only on std{in,out,err} instances.
|
||||
if (MP_OBJ_TO_PTR(self_in) == &mp_sys_stdin_obj) {
|
||||
dest[0] = MP_OBJ_FROM_PTR(&mp_sys_stdin_buffer_obj);
|
||||
return;
|
||||
}
|
||||
if (MP_OBJ_TO_PTR(self_in) == &mp_sys_stdout_obj) {
|
||||
dest[0] = MP_OBJ_FROM_PTR(&mp_sys_stdout_buffer_obj);
|
||||
return;
|
||||
}
|
||||
if (MP_OBJ_TO_PTR(self_in) == &mp_sys_stderr_obj) {
|
||||
dest[0] = MP_OBJ_FROM_PTR(&mp_sys_stderr_buffer_obj);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Any other attribute - forward to locals dict.
|
||||
dest[1] = MP_OBJ_SENTINEL;
|
||||
};
|
||||
|
||||
#define VFS_POSIX_TEXTIO_TYPE_ATTR attr, vfs_posix_textio_attr,
|
||||
|
||||
#else
|
||||
|
||||
#define VFS_POSIX_TEXTIO_TYPE_ATTR
|
||||
|
||||
#endif // MICROPY_PY_SYS_STDIO_BUFFER
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
mp_type_vfs_posix_textio,
|
||||
MP_QSTR_TextIOWrapper,
|
||||
MP_TYPE_FLAG_ITER_IS_STREAM,
|
||||
print, vfs_posix_file_print,
|
||||
protocol, &vfs_posix_textio_stream_p,
|
||||
VFS_POSIX_TEXTIO_TYPE_ATTR
|
||||
locals_dict, &vfs_posix_rawfile_locals_dict
|
||||
);
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit 1bc2c9cb8b8fe4659bd94b8ebba5a4c02029b7fa
|
@ -1,42 +0,0 @@
|
||||
MBEDTLS Error Strings for MicroPython
|
||||
=====================================
|
||||
|
||||
This directory contains source code and tools to rework the Mbedtls error strings for
|
||||
micropython to use less space. In short, instead of storing and printing something like
|
||||
"SSL - Our own certificate(s) is/are too large to send in an SSL message" it prints
|
||||
the name of the error #define, which would be "MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE" in
|
||||
this case, and only stores `SSL_CERTIFICATE_TOO_LARGE` in flash. The exact Mbedtls error
|
||||
defines are used because they're easy to search for to find more detailed information.
|
||||
|
||||
Mbedtls defines a specific format for error value #defines and
|
||||
includes a Perl script to gather all `MBEDTLS_ERR` defines from includes files together with
|
||||
english error text. From that the Perl script generates `mbedtls_strerror()`. The files in this
|
||||
directory modify this process to produce a more space efficient error lookup table with
|
||||
shorter error strings.
|
||||
|
||||
The files are as follows:
|
||||
- `generate_errors.diff` - diff for original mbedtls perl script
|
||||
- `error.fmt` - modified code template for MicroPython
|
||||
- `mp_mbedtls_errors.c` - source file with `mbedtls_strerror` this is built using the include
|
||||
files in `../mbedtls`
|
||||
- `do-mp.sh` - shell script to produce `mp_mbedtls_errors.c`
|
||||
- `tester.c` - simple C main to test `mp_mbedtls_errors.c` locally on a dev box
|
||||
- `do-test.sh` - shell script to produce `mp_mbedtls_errors.c` and compile the `tester` app
|
||||
- `do-esp32.sh` - shell script to produce `esp32_mbedtls_errors.c` -- see below
|
||||
|
||||
In order not to store multiple copies of `mbedtls_errors.c`
|
||||
([https://github.com/micropython/micropython/pull/5819#discussion_r445528006](see))
|
||||
it is assumed that all ports use the same version of mbedtls with the same error #defines.
|
||||
This is true as of MP v1.13, and ESP-IDF versions 3.3.2 and 4.0.1. If anything changes in the
|
||||
future the `do-esp32.sh` script can be used to generate an esp32-specific version.
|
||||
|
||||
### How-to
|
||||
|
||||
- To build MicroPython all that is needed is to include the `mp_mbedtls_errors.c` into the build
|
||||
(the Makefiles do this automatically). Note that Perl is not needed for routine MicroPython
|
||||
builds.
|
||||
- When a new version of Mbedtls is pulled-in the `do-mp.sh` script should be run to
|
||||
re-generate `mp_mbedtls_errors.c`.
|
||||
- The `tester` app should be run if changes to the string handling in `error.fmt` are made:
|
||||
it tests that there is not an off-by-one error in the string copying/appending, etc.
|
||||
- To include `mbedtls_strerror` error strings define `MBEDTLS_ERROR_C` in the build.
|
@ -1,7 +0,0 @@
|
||||
#! /bin/bash -e
|
||||
# Generate esp32_mbedtls_errors.c for use in the Esp32 port, with the ESP-IDF version of mbedtls
|
||||
# The IDF_PATH env var must be set to the top-level dir of ESPIDF
|
||||
echo "IDF_PATH=$IDF_PATH"
|
||||
MBEDTLS=$IDF_PATH/components/mbedtls/mbedtls
|
||||
patch -o esp32_generate_errors.pl $MBEDTLS/scripts/generate_errors.pl <generate_errors.diff
|
||||
perl ./esp32_generate_errors.pl $MBEDTLS/include/mbedtls . esp32_mbedtls_errors.c
|
@ -1,4 +0,0 @@
|
||||
#! /bin/bash -e
|
||||
# Generate mp_mbedtls_errors.c for inclusion in ports that use $MPY/lib/mbedtls
|
||||
patch -o mp_generate_errors.pl ../mbedtls/scripts/generate_errors.pl <generate_errors.diff
|
||||
perl ./mp_generate_errors.pl ../mbedtls/include/mbedtls . mp_mbedtls_errors.c
|
@ -1,4 +0,0 @@
|
||||
#! /bin/bash -e
|
||||
# Generate mp_mbedtls_errors.c and build the tester app
|
||||
./do-mp.sh
|
||||
cc -o tester -I../mbedtls/include/ mp_mbedtls_errors.c tester.c
|
@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Error message information
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
|
||||
#include "mbedtls/error.h"
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#define mbedtls_snprintf snprintf
|
||||
#define mbedtls_time_t time_t
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ERROR_C)
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
HEADER_INCLUDED
|
||||
|
||||
// Error code table type
|
||||
struct ssl_errs {
|
||||
int16_t errnum;
|
||||
const char *errstr;
|
||||
};
|
||||
|
||||
// Table of high level error codes
|
||||
static const struct ssl_errs mbedtls_high_level_error_tab[] = {
|
||||
// BEGIN generated code
|
||||
HIGH_LEVEL_CODE_CHECKS
|
||||
// END generated code
|
||||
};
|
||||
|
||||
static const struct ssl_errs mbedtls_low_level_error_tab[] = {
|
||||
// Low level error codes
|
||||
//
|
||||
// BEGIN generated code
|
||||
LOW_LEVEL_CODE_CHECKS
|
||||
// END generated code
|
||||
};
|
||||
|
||||
static const char *mbedtls_err_prefix = "MBEDTLS_ERR_";
|
||||
#define MBEDTLS_ERR_PREFIX_LEN ( sizeof("MBEDTLS_ERR_")-1 )
|
||||
|
||||
// copy error text into buffer, ensure null termination, return strlen of result
|
||||
static size_t mbedtls_err_to_str(int err, const struct ssl_errs tab[], int tab_len, char *buf, size_t buflen) {
|
||||
if (buflen == 0) return 0;
|
||||
|
||||
// prefix for all error names
|
||||
strncpy(buf, mbedtls_err_prefix, buflen);
|
||||
if (buflen <= MBEDTLS_ERR_PREFIX_LEN+1) {
|
||||
buf[buflen-1] = 0;
|
||||
return buflen-1;
|
||||
}
|
||||
|
||||
// append error name from table
|
||||
for (int i = 0; i < tab_len; i++) {
|
||||
if (tab[i].errnum == err) {
|
||||
strncpy(buf+MBEDTLS_ERR_PREFIX_LEN, tab[i].errstr, buflen-MBEDTLS_ERR_PREFIX_LEN);
|
||||
buf[buflen-1] = 0;
|
||||
return strlen(buf);
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_snprintf(buf+MBEDTLS_ERR_PREFIX_LEN, buflen-MBEDTLS_ERR_PREFIX_LEN, "UNKNOWN (0x%04X)",
|
||||
err);
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
void mbedtls_strerror(int ret, char *buf, size_t buflen) {
|
||||
int use_ret;
|
||||
|
||||
if (buflen == 0) return;
|
||||
|
||||
buf[buflen-1] = 0;
|
||||
|
||||
if (ret < 0) ret = -ret;
|
||||
|
||||
//
|
||||
// High-level error codes
|
||||
//
|
||||
uint8_t got_hl = (ret & 0xFF80) != 0;
|
||||
if (got_hl) {
|
||||
use_ret = ret & 0xFF80;
|
||||
|
||||
// special case
|
||||
#if defined(MBEDTLS_SSL_TLS_C)
|
||||
if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) {
|
||||
strncpy(buf, "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE", buflen);
|
||||
buf[buflen-1] = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t len = mbedtls_err_to_str(use_ret, mbedtls_high_level_error_tab,
|
||||
ARRAY_SIZE(mbedtls_high_level_error_tab), buf, buflen);
|
||||
|
||||
buf += len;
|
||||
buflen -= len;
|
||||
if (buflen == 0) return;
|
||||
}
|
||||
|
||||
//
|
||||
// Low-level error codes
|
||||
//
|
||||
use_ret = ret & ~0xFF80;
|
||||
|
||||
if (use_ret == 0) return;
|
||||
|
||||
// If high level code is present, make a concatenation between both error strings.
|
||||
if (got_hl) {
|
||||
if (buflen < 2) return;
|
||||
*buf++ = '+';
|
||||
buflen--;
|
||||
}
|
||||
|
||||
mbedtls_err_to_str(use_ret, mbedtls_low_level_error_tab,
|
||||
ARRAY_SIZE(mbedtls_low_level_error_tab), buf, buflen);
|
||||
}
|
||||
|
||||
#else /* MBEDTLS_ERROR_C */
|
||||
|
||||
#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
|
||||
|
||||
/*
|
||||
* Provide an non-function in case MBEDTLS_ERROR_C is not defined
|
||||
*/
|
||||
void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
||||
{
|
||||
((void) ret);
|
||||
|
||||
if( buflen > 0 )
|
||||
buf[0] = '\0';
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */
|
||||
|
||||
#endif /* MBEDTLS_ERROR_C */
|
@ -1,22 +0,0 @@
|
||||
--- generate_errors_orig.pl 2020-06-20 08:40:38.819060379 -0700
|
||||
+++ generate_errors.pl 2020-06-20 08:47:26.511163591 -0700
|
||||
@@ -162,16 +162,12 @@
|
||||
|
||||
if ($error_name eq "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE")
|
||||
{
|
||||
- ${$code_check} .= "${white_space}if( use_ret == -($error_name) )\n".
|
||||
- "${white_space}\{\n".
|
||||
- "${white_space} mbedtls_snprintf( buf, buflen, \"$module_name - $description\" );\n".
|
||||
- "${white_space} return;\n".
|
||||
- "${white_space}}\n"
|
||||
+ # no-op, this case is hard-coded in error.fmt
|
||||
}
|
||||
else
|
||||
{
|
||||
- ${$code_check} .= "${white_space}if( use_ret == -($error_name) )\n".
|
||||
- "${white_space} mbedtls_snprintf( buf, buflen, \"$module_name - $description\" );\n"
|
||||
+ my $error_text = $error_name =~ s/^MBEDTLS_ERR_//r;
|
||||
+ ${$code_check} .= "${white_space}{ -($error_name), \"$error_text\" },\n"
|
||||
}
|
||||
};
|
||||
|
@ -1,705 +0,0 @@
|
||||
/*
|
||||
* Error message information
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
|
||||
#include "mbedtls/error.h"
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#define mbedtls_snprintf snprintf
|
||||
#define mbedtls_time_t time_t
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ERROR_C)
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(MBEDTLS_AES_C)
|
||||
#include "mbedtls/aes.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ARC4_C)
|
||||
#include "mbedtls/arc4.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ARIA_C)
|
||||
#include "mbedtls/aria.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_BASE64_C)
|
||||
#include "mbedtls/base64.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_BIGNUM_C)
|
||||
#include "mbedtls/bignum.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_BLOWFISH_C)
|
||||
#include "mbedtls/blowfish.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CAMELLIA_C)
|
||||
#include "mbedtls/camellia.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CCM_C)
|
||||
#include "mbedtls/ccm.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CHACHA20_C)
|
||||
#include "mbedtls/chacha20.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
#include "mbedtls/chachapoly.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_C)
|
||||
#include "mbedtls/cipher.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CMAC_C)
|
||||
#include "mbedtls/cmac.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CTR_DRBG_C)
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_DES_C)
|
||||
#include "mbedtls/des.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_DHM_C)
|
||||
#include "mbedtls/dhm.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
#include "mbedtls/ecp.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ENTROPY_C)
|
||||
#include "mbedtls/entropy.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_GCM_C)
|
||||
#include "mbedtls/gcm.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_HKDF_C)
|
||||
#include "mbedtls/hkdf.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_HMAC_DRBG_C)
|
||||
#include "mbedtls/hmac_drbg.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_MD_C)
|
||||
#include "mbedtls/md.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_MD2_C)
|
||||
#include "mbedtls/md2.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_MD4_C)
|
||||
#include "mbedtls/md4.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_MD5_C)
|
||||
#include "mbedtls/md5.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_NET_C)
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_OID_C)
|
||||
#include "mbedtls/oid.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PADLOCK_C)
|
||||
#include "mbedtls/padlock.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
|
||||
#include "mbedtls/pem.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PK_C)
|
||||
#include "mbedtls/pk.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PKCS12_C)
|
||||
#include "mbedtls/pkcs12.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PKCS5_C)
|
||||
#include "mbedtls/pkcs5.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_POLY1305_C)
|
||||
#include "mbedtls/poly1305.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_RIPEMD160_C)
|
||||
#include "mbedtls/ripemd160.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
#include "mbedtls/rsa.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SHA1_C)
|
||||
#include "mbedtls/sha1.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SHA256_C)
|
||||
#include "mbedtls/sha256.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SHA512_C)
|
||||
#include "mbedtls/sha512.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_TLS_C)
|
||||
#include "mbedtls/ssl.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_THREADING_C)
|
||||
#include "mbedtls/threading.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
|
||||
#include "mbedtls/x509.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_XTEA_C)
|
||||
#include "mbedtls/xtea.h"
|
||||
#endif
|
||||
|
||||
|
||||
// Error code table type
|
||||
struct ssl_errs {
|
||||
int16_t errnum;
|
||||
const char *errstr;
|
||||
};
|
||||
|
||||
// Table of high level error codes
|
||||
static const struct ssl_errs mbedtls_high_level_error_tab[] = {
|
||||
// BEGIN generated code
|
||||
#if defined(MBEDTLS_CIPHER_C)
|
||||
{ -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE), "CIPHER_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA), "CIPHER_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED), "CIPHER_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_CIPHER_INVALID_PADDING), "CIPHER_INVALID_PADDING" },
|
||||
{ -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED), "CIPHER_FULL_BLOCK_EXPECTED" },
|
||||
{ -(MBEDTLS_ERR_CIPHER_AUTH_FAILED), "CIPHER_AUTH_FAILED" },
|
||||
{ -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT), "CIPHER_INVALID_CONTEXT" },
|
||||
{ -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED), "CIPHER_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_CIPHER_C */
|
||||
|
||||
#if defined(MBEDTLS_DHM_C)
|
||||
{ -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA), "DHM_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED), "DHM_READ_PARAMS_FAILED" },
|
||||
{ -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED), "DHM_MAKE_PARAMS_FAILED" },
|
||||
{ -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED), "DHM_READ_PUBLIC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED), "DHM_MAKE_PUBLIC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED), "DHM_CALC_SECRET_FAILED" },
|
||||
{ -(MBEDTLS_ERR_DHM_INVALID_FORMAT), "DHM_INVALID_FORMAT" },
|
||||
{ -(MBEDTLS_ERR_DHM_ALLOC_FAILED), "DHM_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_DHM_FILE_IO_ERROR), "DHM_FILE_IO_ERROR" },
|
||||
{ -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED), "DHM_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED), "DHM_SET_GROUP_FAILED" },
|
||||
#endif /* MBEDTLS_DHM_C */
|
||||
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
{ -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA), "ECP_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL), "ECP_BUFFER_TOO_SMALL" },
|
||||
{ -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE), "ECP_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_ECP_VERIFY_FAILED), "ECP_VERIFY_FAILED" },
|
||||
{ -(MBEDTLS_ERR_ECP_ALLOC_FAILED), "ECP_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_ECP_RANDOM_FAILED), "ECP_RANDOM_FAILED" },
|
||||
{ -(MBEDTLS_ERR_ECP_INVALID_KEY), "ECP_INVALID_KEY" },
|
||||
{ -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH), "ECP_SIG_LEN_MISMATCH" },
|
||||
{ -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED), "ECP_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_ECP_IN_PROGRESS), "ECP_IN_PROGRESS" },
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
|
||||
#if defined(MBEDTLS_MD_C)
|
||||
{ -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE), "MD_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_MD_BAD_INPUT_DATA), "MD_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_MD_ALLOC_FAILED), "MD_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_MD_FILE_IO_ERROR), "MD_FILE_IO_ERROR" },
|
||||
{ -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED), "MD_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_MD_C */
|
||||
|
||||
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
|
||||
{ -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT), "PEM_NO_HEADER_FOOTER_PRESENT" },
|
||||
{ -(MBEDTLS_ERR_PEM_INVALID_DATA), "PEM_INVALID_DATA" },
|
||||
{ -(MBEDTLS_ERR_PEM_ALLOC_FAILED), "PEM_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_PEM_INVALID_ENC_IV), "PEM_INVALID_ENC_IV" },
|
||||
{ -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG), "PEM_UNKNOWN_ENC_ALG" },
|
||||
{ -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED), "PEM_PASSWORD_REQUIRED" },
|
||||
{ -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH), "PEM_PASSWORD_MISMATCH" },
|
||||
{ -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE), "PEM_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA), "PEM_BAD_INPUT_DATA" },
|
||||
#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */
|
||||
|
||||
#if defined(MBEDTLS_PK_C)
|
||||
{ -(MBEDTLS_ERR_PK_ALLOC_FAILED), "PK_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_PK_TYPE_MISMATCH), "PK_TYPE_MISMATCH" },
|
||||
{ -(MBEDTLS_ERR_PK_BAD_INPUT_DATA), "PK_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_PK_FILE_IO_ERROR), "PK_FILE_IO_ERROR" },
|
||||
{ -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION), "PK_KEY_INVALID_VERSION" },
|
||||
{ -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT), "PK_KEY_INVALID_FORMAT" },
|
||||
{ -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG), "PK_UNKNOWN_PK_ALG" },
|
||||
{ -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED), "PK_PASSWORD_REQUIRED" },
|
||||
{ -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH), "PK_PASSWORD_MISMATCH" },
|
||||
{ -(MBEDTLS_ERR_PK_INVALID_PUBKEY), "PK_INVALID_PUBKEY" },
|
||||
{ -(MBEDTLS_ERR_PK_INVALID_ALG), "PK_INVALID_ALG" },
|
||||
{ -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE), "PK_UNKNOWN_NAMED_CURVE" },
|
||||
{ -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE), "PK_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH), "PK_SIG_LEN_MISMATCH" },
|
||||
{ -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED), "PK_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_PK_C */
|
||||
|
||||
#if defined(MBEDTLS_PKCS12_C)
|
||||
{ -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA), "PKCS12_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE), "PKCS12_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT), "PKCS12_PBE_INVALID_FORMAT" },
|
||||
{ -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH), "PKCS12_PASSWORD_MISMATCH" },
|
||||
#endif /* MBEDTLS_PKCS12_C */
|
||||
|
||||
#if defined(MBEDTLS_PKCS5_C)
|
||||
{ -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA), "PKCS5_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT), "PKCS5_INVALID_FORMAT" },
|
||||
{ -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE), "PKCS5_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH), "PKCS5_PASSWORD_MISMATCH" },
|
||||
#endif /* MBEDTLS_PKCS5_C */
|
||||
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
{ -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA), "RSA_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_RSA_INVALID_PADDING), "RSA_INVALID_PADDING" },
|
||||
{ -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED), "RSA_KEY_GEN_FAILED" },
|
||||
{ -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED), "RSA_KEY_CHECK_FAILED" },
|
||||
{ -(MBEDTLS_ERR_RSA_PUBLIC_FAILED), "RSA_PUBLIC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_RSA_PRIVATE_FAILED), "RSA_PRIVATE_FAILED" },
|
||||
{ -(MBEDTLS_ERR_RSA_VERIFY_FAILED), "RSA_VERIFY_FAILED" },
|
||||
{ -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE), "RSA_OUTPUT_TOO_LARGE" },
|
||||
{ -(MBEDTLS_ERR_RSA_RNG_FAILED), "RSA_RNG_FAILED" },
|
||||
{ -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION), "RSA_UNSUPPORTED_OPERATION" },
|
||||
{ -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED), "RSA_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
|
||||
#if defined(MBEDTLS_SSL_TLS_C)
|
||||
{ -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE), "SSL_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA), "SSL_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_SSL_INVALID_MAC), "SSL_INVALID_MAC" },
|
||||
{ -(MBEDTLS_ERR_SSL_INVALID_RECORD), "SSL_INVALID_RECORD" },
|
||||
{ -(MBEDTLS_ERR_SSL_CONN_EOF), "SSL_CONN_EOF" },
|
||||
{ -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER), "SSL_UNKNOWN_CIPHER" },
|
||||
{ -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN), "SSL_NO_CIPHER_CHOSEN" },
|
||||
{ -(MBEDTLS_ERR_SSL_NO_RNG), "SSL_NO_RNG" },
|
||||
{ -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE), "SSL_NO_CLIENT_CERTIFICATE" },
|
||||
{ -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE), "SSL_CERTIFICATE_TOO_LARGE" },
|
||||
{ -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED), "SSL_CERTIFICATE_REQUIRED" },
|
||||
{ -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED), "SSL_PRIVATE_KEY_REQUIRED" },
|
||||
{ -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED), "SSL_CA_CHAIN_REQUIRED" },
|
||||
{ -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE), "SSL_UNEXPECTED_MESSAGE" },
|
||||
{ -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED), "SSL_PEER_VERIFY_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY), "SSL_PEER_CLOSE_NOTIFY" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO), "SSL_BAD_HS_CLIENT_HELLO" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO), "SSL_BAD_HS_SERVER_HELLO" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE), "SSL_BAD_HS_CERTIFICATE" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST), "SSL_BAD_HS_CERTIFICATE_REQUEST" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE), "SSL_BAD_HS_SERVER_KEY_EXCHANGE" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE), "SSL_BAD_HS_SERVER_HELLO_DONE" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY), "SSL_BAD_HS_CERTIFICATE_VERIFY" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC), "SSL_BAD_HS_CHANGE_CIPHER_SPEC" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED), "SSL_BAD_HS_FINISHED" },
|
||||
{ -(MBEDTLS_ERR_SSL_ALLOC_FAILED), "SSL_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED), "SSL_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH), "SSL_HW_ACCEL_FALLTHROUGH" },
|
||||
{ -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED), "SSL_COMPRESSION_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION), "SSL_BAD_HS_PROTOCOL_VERSION" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET), "SSL_BAD_HS_NEW_SESSION_TICKET" },
|
||||
{ -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED), "SSL_SESSION_TICKET_EXPIRED" },
|
||||
{ -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH), "SSL_PK_TYPE_MISMATCH" },
|
||||
{ -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY), "SSL_UNKNOWN_IDENTITY" },
|
||||
{ -(MBEDTLS_ERR_SSL_INTERNAL_ERROR), "SSL_INTERNAL_ERROR" },
|
||||
{ -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING), "SSL_COUNTER_WRAPPING" },
|
||||
{ -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO), "SSL_WAITING_SERVER_HELLO_RENEGO" },
|
||||
{ -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED), "SSL_HELLO_VERIFY_REQUIRED" },
|
||||
{ -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL), "SSL_BUFFER_TOO_SMALL" },
|
||||
{ -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE), "SSL_NO_USABLE_CIPHERSUITE" },
|
||||
{ -(MBEDTLS_ERR_SSL_WANT_READ), "SSL_WANT_READ" },
|
||||
{ -(MBEDTLS_ERR_SSL_WANT_WRITE), "SSL_WANT_WRITE" },
|
||||
{ -(MBEDTLS_ERR_SSL_TIMEOUT), "SSL_TIMEOUT" },
|
||||
{ -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT), "SSL_CLIENT_RECONNECT" },
|
||||
{ -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD), "SSL_UNEXPECTED_RECORD" },
|
||||
{ -(MBEDTLS_ERR_SSL_NON_FATAL), "SSL_NON_FATAL" },
|
||||
{ -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH), "SSL_INVALID_VERIFY_HASH" },
|
||||
{ -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING), "SSL_CONTINUE_PROCESSING" },
|
||||
{ -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS), "SSL_ASYNC_IN_PROGRESS" },
|
||||
{ -(MBEDTLS_ERR_SSL_EARLY_MESSAGE), "SSL_EARLY_MESSAGE" },
|
||||
{ -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS), "SSL_CRYPTO_IN_PROGRESS" },
|
||||
#endif /* MBEDTLS_SSL_TLS_C */
|
||||
|
||||
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
|
||||
{ -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE), "X509_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_X509_UNKNOWN_OID), "X509_UNKNOWN_OID" },
|
||||
{ -(MBEDTLS_ERR_X509_INVALID_FORMAT), "X509_INVALID_FORMAT" },
|
||||
{ -(MBEDTLS_ERR_X509_INVALID_VERSION), "X509_INVALID_VERSION" },
|
||||
{ -(MBEDTLS_ERR_X509_INVALID_SERIAL), "X509_INVALID_SERIAL" },
|
||||
{ -(MBEDTLS_ERR_X509_INVALID_ALG), "X509_INVALID_ALG" },
|
||||
{ -(MBEDTLS_ERR_X509_INVALID_NAME), "X509_INVALID_NAME" },
|
||||
{ -(MBEDTLS_ERR_X509_INVALID_DATE), "X509_INVALID_DATE" },
|
||||
{ -(MBEDTLS_ERR_X509_INVALID_SIGNATURE), "X509_INVALID_SIGNATURE" },
|
||||
{ -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS), "X509_INVALID_EXTENSIONS" },
|
||||
{ -(MBEDTLS_ERR_X509_UNKNOWN_VERSION), "X509_UNKNOWN_VERSION" },
|
||||
{ -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG), "X509_UNKNOWN_SIG_ALG" },
|
||||
{ -(MBEDTLS_ERR_X509_SIG_MISMATCH), "X509_SIG_MISMATCH" },
|
||||
{ -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED), "X509_CERT_VERIFY_FAILED" },
|
||||
{ -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT), "X509_CERT_UNKNOWN_FORMAT" },
|
||||
{ -(MBEDTLS_ERR_X509_BAD_INPUT_DATA), "X509_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_X509_ALLOC_FAILED), "X509_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_X509_FILE_IO_ERROR), "X509_FILE_IO_ERROR" },
|
||||
{ -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL), "X509_BUFFER_TOO_SMALL" },
|
||||
{ -(MBEDTLS_ERR_X509_FATAL_ERROR), "X509_FATAL_ERROR" },
|
||||
#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */
|
||||
// END generated code
|
||||
};
|
||||
|
||||
static const struct ssl_errs mbedtls_low_level_error_tab[] = {
|
||||
// Low level error codes
|
||||
//
|
||||
// BEGIN generated code
|
||||
#if defined(MBEDTLS_AES_C)
|
||||
{ -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH), "AES_INVALID_KEY_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH), "AES_INVALID_INPUT_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_AES_BAD_INPUT_DATA), "AES_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE), "AES_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED), "AES_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_AES_C */
|
||||
|
||||
#if defined(MBEDTLS_ARC4_C)
|
||||
{ -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED), "ARC4_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_ARC4_C */
|
||||
|
||||
#if defined(MBEDTLS_ARIA_C)
|
||||
{ -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA), "ARIA_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH), "ARIA_INVALID_INPUT_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE), "ARIA_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED), "ARIA_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_ARIA_C */
|
||||
|
||||
#if defined(MBEDTLS_ASN1_PARSE_C)
|
||||
{ -(MBEDTLS_ERR_ASN1_OUT_OF_DATA), "ASN1_OUT_OF_DATA" },
|
||||
{ -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG), "ASN1_UNEXPECTED_TAG" },
|
||||
{ -(MBEDTLS_ERR_ASN1_INVALID_LENGTH), "ASN1_INVALID_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH), "ASN1_LENGTH_MISMATCH" },
|
||||
{ -(MBEDTLS_ERR_ASN1_INVALID_DATA), "ASN1_INVALID_DATA" },
|
||||
{ -(MBEDTLS_ERR_ASN1_ALLOC_FAILED), "ASN1_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL), "ASN1_BUF_TOO_SMALL" },
|
||||
#endif /* MBEDTLS_ASN1_PARSE_C */
|
||||
|
||||
#if defined(MBEDTLS_BASE64_C)
|
||||
{ -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL), "BASE64_BUFFER_TOO_SMALL" },
|
||||
{ -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER), "BASE64_INVALID_CHARACTER" },
|
||||
#endif /* MBEDTLS_BASE64_C */
|
||||
|
||||
#if defined(MBEDTLS_BIGNUM_C)
|
||||
{ -(MBEDTLS_ERR_MPI_FILE_IO_ERROR), "MPI_FILE_IO_ERROR" },
|
||||
{ -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA), "MPI_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_MPI_INVALID_CHARACTER), "MPI_INVALID_CHARACTER" },
|
||||
{ -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL), "MPI_BUFFER_TOO_SMALL" },
|
||||
{ -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE), "MPI_NEGATIVE_VALUE" },
|
||||
{ -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO), "MPI_DIVISION_BY_ZERO" },
|
||||
{ -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE), "MPI_NOT_ACCEPTABLE" },
|
||||
{ -(MBEDTLS_ERR_MPI_ALLOC_FAILED), "MPI_ALLOC_FAILED" },
|
||||
#endif /* MBEDTLS_BIGNUM_C */
|
||||
|
||||
#if defined(MBEDTLS_BLOWFISH_C)
|
||||
{ -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA), "BLOWFISH_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH), "BLOWFISH_INVALID_INPUT_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED), "BLOWFISH_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_BLOWFISH_C */
|
||||
|
||||
#if defined(MBEDTLS_CAMELLIA_C)
|
||||
{ -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA), "CAMELLIA_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH), "CAMELLIA_INVALID_INPUT_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED), "CAMELLIA_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_CAMELLIA_C */
|
||||
|
||||
#if defined(MBEDTLS_CCM_C)
|
||||
{ -(MBEDTLS_ERR_CCM_BAD_INPUT), "CCM_BAD_INPUT" },
|
||||
{ -(MBEDTLS_ERR_CCM_AUTH_FAILED), "CCM_AUTH_FAILED" },
|
||||
{ -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED), "CCM_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_CCM_C */
|
||||
|
||||
#if defined(MBEDTLS_CHACHA20_C)
|
||||
{ -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA), "CHACHA20_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE), "CHACHA20_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED), "CHACHA20_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_CHACHA20_C */
|
||||
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
{ -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE), "CHACHAPOLY_BAD_STATE" },
|
||||
{ -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED), "CHACHAPOLY_AUTH_FAILED" },
|
||||
#endif /* MBEDTLS_CHACHAPOLY_C */
|
||||
|
||||
#if defined(MBEDTLS_CMAC_C)
|
||||
{ -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED), "CMAC_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_CMAC_C */
|
||||
|
||||
#if defined(MBEDTLS_CTR_DRBG_C)
|
||||
{ -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED), "CTR_DRBG_ENTROPY_SOURCE_FAILED" },
|
||||
{ -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG), "CTR_DRBG_REQUEST_TOO_BIG" },
|
||||
{ -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG), "CTR_DRBG_INPUT_TOO_BIG" },
|
||||
{ -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR), "CTR_DRBG_FILE_IO_ERROR" },
|
||||
#endif /* MBEDTLS_CTR_DRBG_C */
|
||||
|
||||
#if defined(MBEDTLS_DES_C)
|
||||
{ -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH), "DES_INVALID_INPUT_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED), "DES_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_DES_C */
|
||||
|
||||
#if defined(MBEDTLS_ENTROPY_C)
|
||||
{ -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED), "ENTROPY_SOURCE_FAILED" },
|
||||
{ -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES), "ENTROPY_MAX_SOURCES" },
|
||||
{ -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED), "ENTROPY_NO_SOURCES_DEFINED" },
|
||||
{ -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE), "ENTROPY_NO_STRONG_SOURCE" },
|
||||
{ -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR), "ENTROPY_FILE_IO_ERROR" },
|
||||
#endif /* MBEDTLS_ENTROPY_C */
|
||||
|
||||
#if defined(MBEDTLS_GCM_C)
|
||||
{ -(MBEDTLS_ERR_GCM_AUTH_FAILED), "GCM_AUTH_FAILED" },
|
||||
{ -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED), "GCM_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_GCM_BAD_INPUT), "GCM_BAD_INPUT" },
|
||||
#endif /* MBEDTLS_GCM_C */
|
||||
|
||||
#if defined(MBEDTLS_HKDF_C)
|
||||
{ -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA), "HKDF_BAD_INPUT_DATA" },
|
||||
#endif /* MBEDTLS_HKDF_C */
|
||||
|
||||
#if defined(MBEDTLS_HMAC_DRBG_C)
|
||||
{ -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG), "HMAC_DRBG_REQUEST_TOO_BIG" },
|
||||
{ -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG), "HMAC_DRBG_INPUT_TOO_BIG" },
|
||||
{ -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR), "HMAC_DRBG_FILE_IO_ERROR" },
|
||||
{ -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED), "HMAC_DRBG_ENTROPY_SOURCE_FAILED" },
|
||||
#endif /* MBEDTLS_HMAC_DRBG_C */
|
||||
|
||||
#if defined(MBEDTLS_MD2_C)
|
||||
{ -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED), "MD2_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_MD2_C */
|
||||
|
||||
#if defined(MBEDTLS_MD4_C)
|
||||
{ -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED), "MD4_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_MD4_C */
|
||||
|
||||
#if defined(MBEDTLS_MD5_C)
|
||||
{ -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED), "MD5_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_MD5_C */
|
||||
|
||||
#if defined(MBEDTLS_NET_C)
|
||||
{ -(MBEDTLS_ERR_NET_SOCKET_FAILED), "NET_SOCKET_FAILED" },
|
||||
{ -(MBEDTLS_ERR_NET_CONNECT_FAILED), "NET_CONNECT_FAILED" },
|
||||
{ -(MBEDTLS_ERR_NET_BIND_FAILED), "NET_BIND_FAILED" },
|
||||
{ -(MBEDTLS_ERR_NET_LISTEN_FAILED), "NET_LISTEN_FAILED" },
|
||||
{ -(MBEDTLS_ERR_NET_ACCEPT_FAILED), "NET_ACCEPT_FAILED" },
|
||||
{ -(MBEDTLS_ERR_NET_RECV_FAILED), "NET_RECV_FAILED" },
|
||||
{ -(MBEDTLS_ERR_NET_SEND_FAILED), "NET_SEND_FAILED" },
|
||||
{ -(MBEDTLS_ERR_NET_CONN_RESET), "NET_CONN_RESET" },
|
||||
{ -(MBEDTLS_ERR_NET_UNKNOWN_HOST), "NET_UNKNOWN_HOST" },
|
||||
{ -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL), "NET_BUFFER_TOO_SMALL" },
|
||||
{ -(MBEDTLS_ERR_NET_INVALID_CONTEXT), "NET_INVALID_CONTEXT" },
|
||||
{ -(MBEDTLS_ERR_NET_POLL_FAILED), "NET_POLL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_NET_BAD_INPUT_DATA), "NET_BAD_INPUT_DATA" },
|
||||
#endif /* MBEDTLS_NET_C */
|
||||
|
||||
#if defined(MBEDTLS_OID_C)
|
||||
{ -(MBEDTLS_ERR_OID_NOT_FOUND), "OID_NOT_FOUND" },
|
||||
{ -(MBEDTLS_ERR_OID_BUF_TOO_SMALL), "OID_BUF_TOO_SMALL" },
|
||||
#endif /* MBEDTLS_OID_C */
|
||||
|
||||
#if defined(MBEDTLS_PADLOCK_C)
|
||||
{ -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED), "PADLOCK_DATA_MISALIGNED" },
|
||||
#endif /* MBEDTLS_PADLOCK_C */
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
{ -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED), "PLATFORM_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED), "PLATFORM_FEATURE_UNSUPPORTED" },
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
|
||||
#if defined(MBEDTLS_POLY1305_C)
|
||||
{ -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA), "POLY1305_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE), "POLY1305_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED), "POLY1305_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_POLY1305_C */
|
||||
|
||||
#if defined(MBEDTLS_RIPEMD160_C)
|
||||
{ -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED), "RIPEMD160_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_RIPEMD160_C */
|
||||
|
||||
#if defined(MBEDTLS_SHA1_C)
|
||||
{ -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED), "SHA1_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA), "SHA1_BAD_INPUT_DATA" },
|
||||
#endif /* MBEDTLS_SHA1_C */
|
||||
|
||||
#if defined(MBEDTLS_SHA256_C)
|
||||
{ -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED), "SHA256_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA), "SHA256_BAD_INPUT_DATA" },
|
||||
#endif /* MBEDTLS_SHA256_C */
|
||||
|
||||
#if defined(MBEDTLS_SHA512_C)
|
||||
{ -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED), "SHA512_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA), "SHA512_BAD_INPUT_DATA" },
|
||||
#endif /* MBEDTLS_SHA512_C */
|
||||
|
||||
#if defined(MBEDTLS_THREADING_C)
|
||||
{ -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE), "THREADING_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA), "THREADING_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_THREADING_MUTEX_ERROR), "THREADING_MUTEX_ERROR" },
|
||||
#endif /* MBEDTLS_THREADING_C */
|
||||
|
||||
#if defined(MBEDTLS_XTEA_C)
|
||||
{ -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH), "XTEA_INVALID_INPUT_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED), "XTEA_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_XTEA_C */
|
||||
// END generated code
|
||||
};
|
||||
|
||||
static const char *mbedtls_err_prefix = "MBEDTLS_ERR_";
|
||||
#define MBEDTLS_ERR_PREFIX_LEN ( sizeof("MBEDTLS_ERR_")-1 )
|
||||
|
||||
// copy error text into buffer, ensure null termination, return strlen of result
|
||||
static size_t mbedtls_err_to_str(int err, const struct ssl_errs tab[], int tab_len, char *buf, size_t buflen) {
|
||||
if (buflen == 0) return 0;
|
||||
|
||||
// prefix for all error names
|
||||
strncpy(buf, mbedtls_err_prefix, buflen);
|
||||
if (buflen <= MBEDTLS_ERR_PREFIX_LEN+1) {
|
||||
buf[buflen-1] = 0;
|
||||
return buflen-1;
|
||||
}
|
||||
|
||||
// append error name from table
|
||||
for (int i = 0; i < tab_len; i++) {
|
||||
if (tab[i].errnum == err) {
|
||||
strncpy(buf+MBEDTLS_ERR_PREFIX_LEN, tab[i].errstr, buflen-MBEDTLS_ERR_PREFIX_LEN);
|
||||
buf[buflen-1] = 0;
|
||||
return strlen(buf);
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_snprintf(buf+MBEDTLS_ERR_PREFIX_LEN, buflen-MBEDTLS_ERR_PREFIX_LEN, "UNKNOWN (0x%04X)",
|
||||
err);
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
void mbedtls_strerror(int ret, char *buf, size_t buflen) {
|
||||
int use_ret;
|
||||
|
||||
if (buflen == 0) return;
|
||||
|
||||
buf[buflen-1] = 0;
|
||||
|
||||
if (ret < 0) ret = -ret;
|
||||
|
||||
//
|
||||
// High-level error codes
|
||||
//
|
||||
uint8_t got_hl = (ret & 0xFF80) != 0;
|
||||
if (got_hl) {
|
||||
use_ret = ret & 0xFF80;
|
||||
|
||||
// special case
|
||||
#if defined(MBEDTLS_SSL_TLS_C)
|
||||
if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) {
|
||||
strncpy(buf, "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE", buflen);
|
||||
buf[buflen-1] = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t len = mbedtls_err_to_str(use_ret, mbedtls_high_level_error_tab,
|
||||
ARRAY_SIZE(mbedtls_high_level_error_tab), buf, buflen);
|
||||
|
||||
buf += len;
|
||||
buflen -= len;
|
||||
if (buflen == 0) return;
|
||||
}
|
||||
|
||||
//
|
||||
// Low-level error codes
|
||||
//
|
||||
use_ret = ret & ~0xFF80;
|
||||
|
||||
if (use_ret == 0) return;
|
||||
|
||||
// If high level code is present, make a concatenation between both error strings.
|
||||
if (got_hl) {
|
||||
if (buflen < 2) return;
|
||||
*buf++ = '+';
|
||||
buflen--;
|
||||
}
|
||||
|
||||
mbedtls_err_to_str(use_ret, mbedtls_low_level_error_tab,
|
||||
ARRAY_SIZE(mbedtls_low_level_error_tab), buf, buflen);
|
||||
}
|
||||
|
||||
#else /* MBEDTLS_ERROR_C */
|
||||
|
||||
#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
|
||||
|
||||
/*
|
||||
* Provide an non-function in case MBEDTLS_ERROR_C is not defined
|
||||
*/
|
||||
void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
||||
{
|
||||
((void) ret);
|
||||
|
||||
if( buflen > 0 )
|
||||
buf[0] = '\0';
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */
|
||||
|
||||
#endif /* MBEDTLS_ERROR_C */
|
@ -1,58 +0,0 @@
|
||||
#include "mbedtls/error.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// test_code checks that the provided code results in the provided error string for any size
|
||||
// buffer. It calls mbedtls_strerror() to fill a buffer that is from 1 to 100 bytes in length
|
||||
// and then checks that the buffer contents is OK and that a few guard bytes before and after
|
||||
// the buffer were not overwritten.
|
||||
int test_code(int code, char *str) {
|
||||
char buf[100];
|
||||
int ok = 1;
|
||||
int res;
|
||||
|
||||
// test zero-length buffer
|
||||
memset(buf, -3, 100);
|
||||
mbedtls_strerror(code, buf + 4, 0);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (buf[i] != -3) {
|
||||
printf("Error: guard overwritten buflen=0 i=%d buf[i]=%d\n", i, buf[i]);
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// test
|
||||
for (size_t buflen = 1; buflen < 90; buflen++) {
|
||||
memset(buf, -3, 100);
|
||||
mbedtls_strerror(code, buf + 4, buflen);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (buf[i] != -3) {
|
||||
printf("Error: pre-guard overwritten buflen=%d i=%d buf[i]=%d\n", buflen, i, buf[i]);
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
for (int i = 4 + buflen; i < 100; i++) {
|
||||
if (buf[i] != -3) {
|
||||
printf("Error: post-guard overwritten buflen=%d i=%d buf[i]=%d\n", buflen, i, buf[i]);
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
char exp[100];
|
||||
strncpy(exp, str, buflen);
|
||||
exp[buflen - 1] = 0;
|
||||
if (strcmp(buf + 4, exp) != 0) {
|
||||
printf("Error: expected %s, got %s\n", exp, buf);
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Test %x -> %s is %s\n", code, str, ok?"OK":"*** BAD ***");
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_code(0x7200, "MBEDTLS_ERR_SSL_INVALID_RECORD");
|
||||
test_code(0x7780, "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE");
|
||||
test_code(0x0074, "MBEDTLS_ERR_SHA256_BAD_INPUT_DATA");
|
||||
test_code(0x6600 | 0x0074, "MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH+MBEDTLS_ERR_SHA256_BAD_INPUT_DATA");
|
||||
test_code(103, "MBEDTLS_ERR_UNKNOWN (0x0067)");
|
||||
}
|
@ -1 +1 @@
|
||||
Subproject commit e6b89eafa3b86d2e8e405450377d459600a30cd6
|
||||
Subproject commit e025c843b60e93689f0f991d753010bb5bd6a722
|
@ -2834,7 +2834,7 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not
|
||||
if (di >= FF_MAX_LFN) return FR_INVALID_NAME; /* Reject too long name */
|
||||
lfn[di++] = wc; /* Store the Unicode character */
|
||||
}
|
||||
while (*p == '/' || *p == '\\') p++; /* Skip duplicated separators if exist */
|
||||
if (wc == '/' || wc == '\\') while (*p == '/' || *p == '\\') p++; /* Skip duplicated separators if exist */
|
||||
*path = p; /* Return pointer to the next segment */
|
||||
cf = (wc < ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
* Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
|
||||
*/
|
||||
|
||||
#include "tinf.h"
|
||||
#include "uzlib.h"
|
||||
|
||||
#define A32_BASE 65521
|
||||
#define A32_NMAX 5552
|
||||
|
@ -36,7 +36,7 @@
|
||||
* Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
|
||||
*/
|
||||
|
||||
#include "tinf.h"
|
||||
#include "uzlib.h"
|
||||
|
||||
static const unsigned int tinf_crc32tab[16] = {
|
||||
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190,
|
||||
|
181
lib/uzlib/defl_static.c
Normal file
181
lib/uzlib/defl_static.c
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
|
||||
Routines in this file are based on:
|
||||
Zlib (RFC1950 / RFC1951) compression for PuTTY.
|
||||
|
||||
PuTTY is copyright 1997-2014 Simon Tatham.
|
||||
|
||||
Portions copyright Robert de Bath, Joris van Rantwijk, Delian
|
||||
Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
|
||||
Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
|
||||
Kuhn, Colin Watson, and CORE SDI S.A.
|
||||
|
||||
Optimised for MicroPython:
|
||||
Copyright (c) 2023 by Jim Mussared
|
||||
|
||||
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 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Zlib compression. We always use the static Huffman tree option.
|
||||
* Mostly this is because it's hard to scan a block in advance to
|
||||
* work out better trees; dynamic trees are great when you're
|
||||
* compressing a large file under no significant time constraint,
|
||||
* but when you're compressing little bits in real time, things get
|
||||
* hairier.
|
||||
*
|
||||
* I suppose it's possible that I could compute Huffman trees based
|
||||
* on the frequencies in the _previous_ block, as a sort of
|
||||
* heuristic, but I'm not confident that the gain would balance out
|
||||
* having to transmit the trees.
|
||||
*/
|
||||
|
||||
static void outbits(uzlib_lz77_state_t *state, unsigned long bits, int nbits)
|
||||
{
|
||||
assert(state->noutbits + nbits <= 32);
|
||||
state->outbits |= bits << state->noutbits;
|
||||
state->noutbits += nbits;
|
||||
while (state->noutbits >= 8) {
|
||||
state->dest_write_cb(state->dest_write_data, state->outbits & 0xFF);
|
||||
state->outbits >>= 8;
|
||||
state->noutbits -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char mirrornibbles[16] = {
|
||||
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
|
||||
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf,
|
||||
};
|
||||
|
||||
static unsigned int mirrorbyte(unsigned int b) {
|
||||
return mirrornibbles[b & 0xf] << 4 | mirrornibbles[b >> 4];
|
||||
}
|
||||
|
||||
static int int_log2(int x) {
|
||||
int r = 0;
|
||||
while (x >>= 1) {
|
||||
++r;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static void uzlib_literal(uzlib_lz77_state_t *state, unsigned char c)
|
||||
{
|
||||
if (c <= 143) {
|
||||
/* 0 through 143 are 8 bits long starting at 00110000. */
|
||||
outbits(state, mirrorbyte(0x30 + c), 8);
|
||||
} else {
|
||||
/* 144 through 255 are 9 bits long starting at 110010000. */
|
||||
outbits(state, 1 + 2 * mirrorbyte(0x90 - 144 + c), 9);
|
||||
}
|
||||
}
|
||||
|
||||
static void uzlib_match(uzlib_lz77_state_t *state, int distance, int len)
|
||||
{
|
||||
assert(distance >= 1 && distance <= 32768);
|
||||
distance -= 1;
|
||||
|
||||
while (len > 0) {
|
||||
int thislen;
|
||||
|
||||
/*
|
||||
* We can transmit matches of lengths 3 through 258
|
||||
* inclusive. So if len exceeds 258, we must transmit in
|
||||
* several steps, with 258 or less in each step.
|
||||
*
|
||||
* Specifically: if len >= 261, we can transmit 258 and be
|
||||
* sure of having at least 3 left for the next step. And if
|
||||
* len <= 258, we can just transmit len. But if len == 259
|
||||
* or 260, we must transmit len-3.
|
||||
*/
|
||||
thislen = (len > 260 ? 258 : len <= 258 ? len : len - 3);
|
||||
len -= thislen;
|
||||
|
||||
assert(thislen >= 3 && thislen <= 258);
|
||||
|
||||
thislen -= 3;
|
||||
int lcode = 28;
|
||||
int x = int_log2(thislen);
|
||||
int y;
|
||||
if (thislen < 255) {
|
||||
if (x) {
|
||||
--x;
|
||||
}
|
||||
y = (thislen >> (x ? x - 1 : 0)) & 3;
|
||||
lcode = x * 4 + y;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transmit the length code. 256-279 are seven bits
|
||||
* starting at 0000000; 280-287 are eight bits starting at
|
||||
* 11000000.
|
||||
*/
|
||||
if (lcode <= 22) {
|
||||
outbits(state, mirrorbyte((lcode + 1) * 2), 7);
|
||||
} else {
|
||||
outbits(state, mirrorbyte(lcode + 169), 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Transmit the extra bits.
|
||||
*/
|
||||
if (thislen < 255 && x > 1) {
|
||||
int extrabits = x - 1;
|
||||
int lmin = (thislen >> extrabits) << extrabits;
|
||||
outbits(state, thislen - lmin, extrabits);
|
||||
}
|
||||
|
||||
x = int_log2(distance);
|
||||
y = (distance >> (x ? x - 1 : 0)) & 1;
|
||||
|
||||
/*
|
||||
* Transmit the distance code. Five bits starting at 00000.
|
||||
*/
|
||||
outbits(state, mirrorbyte((x * 2 + y) * 8), 5);
|
||||
|
||||
/*
|
||||
* Transmit the extra bits.
|
||||
*/
|
||||
if (x > 1) {
|
||||
int dextrabits = x - 1;
|
||||
int dmin = (distance >> dextrabits) << dextrabits;
|
||||
outbits(state, distance - dmin, dextrabits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uzlib_start_block(uzlib_lz77_state_t *state)
|
||||
{
|
||||
// Final block (0b1)
|
||||
// Static huffman block (0b01)
|
||||
outbits(state, 3, 3);
|
||||
}
|
||||
|
||||
void uzlib_finish_block(uzlib_lz77_state_t *state)
|
||||
{
|
||||
// Close block (0b0000000)
|
||||
// Make sure all bits are flushed (0b0000000)
|
||||
outbits(state, 0, 14);
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) uzlib authors
|
||||
*
|
||||
* This software is provided 'as-is', without any express
|
||||
* or implied warranty. In no event will the authors be
|
||||
* held liable for any damages arising from the use of
|
||||
* this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software
|
||||
* for any purpose, including commercial applications,
|
||||
* and to alter it and redistribute it freely, subject to
|
||||
* the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be
|
||||
* misrepresented; you must not claim that you
|
||||
* wrote the original software. If you use this
|
||||
* software in a product, an acknowledgment in
|
||||
* the product documentation would be appreciated
|
||||
* but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked
|
||||
* as such, and must not be misrepresented as
|
||||
* being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from
|
||||
* any source distribution.
|
||||
*/
|
||||
|
||||
/* This files contains type declaration and prototypes for defl_static.c.
|
||||
They may be altered/distinct from the originals used in PuTTY source
|
||||
code. */
|
||||
|
||||
struct Outbuf {
|
||||
unsigned char *outbuf;
|
||||
int outlen, outsize;
|
||||
unsigned long outbits;
|
||||
int noutbits;
|
||||
int comp_disabled;
|
||||
};
|
||||
|
||||
void outbits(struct Outbuf *out, unsigned long bits, int nbits);
|
||||
void zlib_start_block(struct Outbuf *ctx);
|
||||
void zlib_finish_block(struct Outbuf *ctx);
|
||||
void zlib_literal(struct Outbuf *ectx, unsigned char c);
|
||||
void zlib_match(struct Outbuf *ectx, int distance, int len);
|
137
lib/uzlib/header.c
Normal file
137
lib/uzlib/header.c
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* uzlib - tiny deflate/inflate library (deflate, gzip, zlib)
|
||||
*
|
||||
* Copyright (c) 2003 by Joergen Ibsen / Jibz
|
||||
* All Rights Reserved
|
||||
*
|
||||
* http://www.ibsensoftware.com/
|
||||
*
|
||||
* Copyright (c) 2014-2018 by Paul Sokolovsky
|
||||
*
|
||||
* Optimised for MicroPython:
|
||||
* Copyright (c) 2023 by Jim Mussared
|
||||
*
|
||||
* This software is provided 'as-is', without any express
|
||||
* or implied warranty. In no event will the authors be
|
||||
* held liable for any damages arising from the use of
|
||||
* this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software
|
||||
* for any purpose, including commercial applications,
|
||||
* and to alter it and redistribute it freely, subject to
|
||||
* the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be
|
||||
* misrepresented; you must not claim that you
|
||||
* wrote the original software. If you use this
|
||||
* software in a product, an acknowledgment in
|
||||
* the product documentation would be appreciated
|
||||
* but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked
|
||||
* as such, and must not be misrepresented as
|
||||
* being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from
|
||||
* any source distribution.
|
||||
*/
|
||||
|
||||
#include "uzlib.h"
|
||||
|
||||
#define FTEXT 1
|
||||
#define FHCRC 2
|
||||
#define FEXTRA 4
|
||||
#define FNAME 8
|
||||
#define FCOMMENT 16
|
||||
|
||||
void tinf_skip_bytes(uzlib_uncomp_t *d, int num);
|
||||
uint16_t tinf_get_uint16(uzlib_uncomp_t *d);
|
||||
|
||||
void tinf_skip_bytes(uzlib_uncomp_t *d, int num)
|
||||
{
|
||||
while (num--) uzlib_get_byte(d);
|
||||
}
|
||||
|
||||
uint16_t tinf_get_uint16(uzlib_uncomp_t *d)
|
||||
{
|
||||
unsigned int v = uzlib_get_byte(d);
|
||||
v = (uzlib_get_byte(d) << 8) | v;
|
||||
return v;
|
||||
}
|
||||
|
||||
int uzlib_parse_zlib_gzip_header(uzlib_uncomp_t *d, int *wbits)
|
||||
{
|
||||
/* -- check format -- */
|
||||
unsigned char cmf = uzlib_get_byte(d);
|
||||
unsigned char flg = uzlib_get_byte(d);
|
||||
|
||||
/* check for gzip id bytes */
|
||||
if (cmf == 0x1f && flg == 0x8b) {
|
||||
/* check method is deflate */
|
||||
if (uzlib_get_byte(d) != 8) return UZLIB_DATA_ERROR;
|
||||
|
||||
/* get flag byte */
|
||||
flg = uzlib_get_byte(d);
|
||||
|
||||
/* check that reserved bits are zero */
|
||||
if (flg & 0xe0) return UZLIB_DATA_ERROR;
|
||||
|
||||
/* -- find start of compressed data -- */
|
||||
|
||||
/* skip rest of base header of 10 bytes */
|
||||
tinf_skip_bytes(d, 6);
|
||||
|
||||
/* skip extra data if present */
|
||||
if (flg & FEXTRA)
|
||||
{
|
||||
unsigned int xlen = tinf_get_uint16(d);
|
||||
tinf_skip_bytes(d, xlen);
|
||||
}
|
||||
|
||||
/* skip file name if present */
|
||||
if (flg & FNAME) { while (uzlib_get_byte(d)); }
|
||||
|
||||
/* skip file comment if present */
|
||||
if (flg & FCOMMENT) { while (uzlib_get_byte(d)); }
|
||||
|
||||
/* check header crc if present */
|
||||
if (flg & FHCRC)
|
||||
{
|
||||
/*unsigned int hcrc =*/ tinf_get_uint16(d);
|
||||
|
||||
// TODO: Check!
|
||||
// if (hcrc != (tinf_crc32(src, start - src) & 0x0000ffff))
|
||||
// return UZLIB_DATA_ERROR;
|
||||
}
|
||||
|
||||
/* initialize for crc32 checksum */
|
||||
d->checksum_type = UZLIB_CHKSUM_CRC;
|
||||
d->checksum = ~0;
|
||||
|
||||
/* gzip does not include the window size in the header, as it is expected that a
|
||||
compressor will use wbits=15 (32kiB).*/
|
||||
*wbits = 15;
|
||||
|
||||
return UZLIB_HEADER_GZIP;
|
||||
} else {
|
||||
/* check checksum */
|
||||
if ((256*cmf + flg) % 31) return UZLIB_DATA_ERROR;
|
||||
|
||||
/* check method is deflate */
|
||||
if ((cmf & 0x0f) != 8) return UZLIB_DATA_ERROR;
|
||||
|
||||
/* check window size is valid */
|
||||
if ((cmf >> 4) > 7) return UZLIB_DATA_ERROR;
|
||||
|
||||
/* check there is no preset dictionary */
|
||||
if (flg & 0x20) return UZLIB_DATA_ERROR;
|
||||
|
||||
/* initialize for adler32 checksum */
|
||||
d->checksum_type = UZLIB_CHKSUM_ADLER;
|
||||
d->checksum = 1;
|
||||
|
||||
*wbits = (cmf >> 4) + 8;
|
||||
|
||||
return UZLIB_HEADER_ZLIB;
|
||||
}
|
||||
}
|
87
lib/uzlib/lz77.c
Normal file
87
lib/uzlib/lz77.c
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Simple LZ77 streaming compressor.
|
||||
*
|
||||
* The scheme implemented here doesn't use a hash table and instead does a brute
|
||||
* force search in the history for a previous string. It is relatively slow
|
||||
* (but still O(N)) but gives good compression and minimal memory usage. For a
|
||||
* small history window (eg 256 bytes) it's not too slow and compresses well.
|
||||
*
|
||||
* MIT license; Copyright (c) 2021 Damien P. George
|
||||
*/
|
||||
|
||||
#include "uzlib.h"
|
||||
|
||||
#include "defl_static.c"
|
||||
|
||||
#define MATCH_LEN_MIN (3)
|
||||
#define MATCH_LEN_MAX (258)
|
||||
|
||||
// hist should be a preallocated buffer of hist_max size bytes.
|
||||
// hist_max should be greater than 0 a power of 2 (ie 1, 2, 4, 8, ...).
|
||||
// It's possible to pass in hist=NULL, and then the history window will be taken from the
|
||||
// src passed in to uzlib_lz77_compress (this is useful when not doing streaming compression).
|
||||
void uzlib_lz77_init(uzlib_lz77_state_t *state, uint8_t *hist, size_t hist_max) {
|
||||
memset(state, 0, sizeof(uzlib_lz77_state_t));
|
||||
state->hist_buf = hist;
|
||||
state->hist_max = hist_max;
|
||||
state->hist_start = 0;
|
||||
state->hist_len = 0;
|
||||
}
|
||||
|
||||
// Push the given byte to the history.
|
||||
// Search back in the history for the maximum match of the given src data,
|
||||
// with support for searching beyond the end of the history and into the src buffer
|
||||
// (effectively the history and src buffer are concatenated).
|
||||
static size_t uzlib_lz77_search_max_match(uzlib_lz77_state_t *state, const uint8_t *src, size_t len, size_t *longest_offset) {
|
||||
size_t longest_len = 0;
|
||||
for (size_t hist_search = 0; hist_search < state->hist_len; ++hist_search) {
|
||||
size_t match_len;
|
||||
for (match_len = 0; match_len <= MATCH_LEN_MAX && match_len < len; ++match_len) {
|
||||
uint8_t hist;
|
||||
if (hist_search + match_len < state->hist_len) {
|
||||
hist = state->hist_buf[(state->hist_start + hist_search + match_len) & (state->hist_max - 1)];
|
||||
} else {
|
||||
hist = src[hist_search + match_len - state->hist_len];
|
||||
}
|
||||
if (src[match_len] != hist) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match_len >= MATCH_LEN_MIN && match_len > longest_len) {
|
||||
longest_len = match_len;
|
||||
*longest_offset = state->hist_len - hist_search;
|
||||
}
|
||||
}
|
||||
|
||||
return longest_len;
|
||||
}
|
||||
|
||||
// Compress the given chunk of data.
|
||||
void uzlib_lz77_compress(uzlib_lz77_state_t *state, const uint8_t *src, unsigned len) {
|
||||
const uint8_t *top = src + len;
|
||||
while (src < top) {
|
||||
// Look for a match in the history window.
|
||||
size_t match_offset = 0;
|
||||
size_t match_len = uzlib_lz77_search_max_match(state, src, top - src, &match_offset);
|
||||
|
||||
// Encode the literal byte or the match.
|
||||
if (match_len == 0) {
|
||||
uzlib_literal(state, *src);
|
||||
match_len = 1;
|
||||
} else {
|
||||
uzlib_match(state, match_offset, match_len);
|
||||
}
|
||||
|
||||
// Push the bytes into the history buffer.
|
||||
size_t mask = state->hist_max - 1;
|
||||
while (match_len--) {
|
||||
uint8_t b = *src++;
|
||||
state->hist_buf[(state->hist_start + state->hist_len) & mask] = b;
|
||||
if (state->hist_len == state->hist_max) {
|
||||
state->hist_start = (state->hist_start + 1) & mask;
|
||||
} else {
|
||||
++state->hist_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
/* Compatibility header for the original tinf lib/older versions of uzlib.
|
||||
Note: may be removed in the future, please migrate to uzlib.h. */
|
||||
#include "uzlib.h"
|
@ -1,9 +0,0 @@
|
||||
/* This header contains compatibility defines for the original tinf API
|
||||
and uzlib 2.x and below API. These defines are deprecated and going
|
||||
to be removed in the future, so applications should migrate to new
|
||||
uzlib API. */
|
||||
#define TINF_DATA struct uzlib_uncomp
|
||||
|
||||
#define destSize dest_size
|
||||
#define destStart dest_start
|
||||
#define readSource source_read_cb
|
@ -1,110 +0,0 @@
|
||||
/*
|
||||
* uzlib - tiny deflate/inflate library (deflate, gzip, zlib)
|
||||
*
|
||||
* Copyright (c) 2003 by Joergen Ibsen / Jibz
|
||||
* All Rights Reserved
|
||||
*
|
||||
* http://www.ibsensoftware.com/
|
||||
*
|
||||
* Copyright (c) 2014-2018 by Paul Sokolovsky
|
||||
*
|
||||
* This software is provided 'as-is', without any express
|
||||
* or implied warranty. In no event will the authors be
|
||||
* held liable for any damages arising from the use of
|
||||
* this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software
|
||||
* for any purpose, including commercial applications,
|
||||
* and to alter it and redistribute it freely, subject to
|
||||
* the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be
|
||||
* misrepresented; you must not claim that you
|
||||
* wrote the original software. If you use this
|
||||
* software in a product, an acknowledgment in
|
||||
* the product documentation would be appreciated
|
||||
* but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked
|
||||
* as such, and must not be misrepresented as
|
||||
* being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from
|
||||
* any source distribution.
|
||||
*/
|
||||
|
||||
#include "tinf.h"
|
||||
|
||||
#define FTEXT 1
|
||||
#define FHCRC 2
|
||||
#define FEXTRA 4
|
||||
#define FNAME 8
|
||||
#define FCOMMENT 16
|
||||
|
||||
void tinf_skip_bytes(TINF_DATA *d, int num);
|
||||
uint16_t tinf_get_uint16(TINF_DATA *d);
|
||||
|
||||
void tinf_skip_bytes(TINF_DATA *d, int num)
|
||||
{
|
||||
while (num--) uzlib_get_byte(d);
|
||||
}
|
||||
|
||||
uint16_t tinf_get_uint16(TINF_DATA *d)
|
||||
{
|
||||
unsigned int v = uzlib_get_byte(d);
|
||||
v = (uzlib_get_byte(d) << 8) | v;
|
||||
return v;
|
||||
}
|
||||
|
||||
int uzlib_gzip_parse_header(TINF_DATA *d)
|
||||
{
|
||||
unsigned char flg;
|
||||
|
||||
/* -- check format -- */
|
||||
|
||||
/* check id bytes */
|
||||
if (uzlib_get_byte(d) != 0x1f || uzlib_get_byte(d) != 0x8b) return TINF_DATA_ERROR;
|
||||
|
||||
/* check method is deflate */
|
||||
if (uzlib_get_byte(d) != 8) return TINF_DATA_ERROR;
|
||||
|
||||
/* get flag byte */
|
||||
flg = uzlib_get_byte(d);
|
||||
|
||||
/* check that reserved bits are zero */
|
||||
if (flg & 0xe0) return TINF_DATA_ERROR;
|
||||
|
||||
/* -- find start of compressed data -- */
|
||||
|
||||
/* skip rest of base header of 10 bytes */
|
||||
tinf_skip_bytes(d, 6);
|
||||
|
||||
/* skip extra data if present */
|
||||
if (flg & FEXTRA)
|
||||
{
|
||||
unsigned int xlen = tinf_get_uint16(d);
|
||||
tinf_skip_bytes(d, xlen);
|
||||
}
|
||||
|
||||
/* skip file name if present */
|
||||
if (flg & FNAME) { while (uzlib_get_byte(d)); }
|
||||
|
||||
/* skip file comment if present */
|
||||
if (flg & FCOMMENT) { while (uzlib_get_byte(d)); }
|
||||
|
||||
/* check header crc if present */
|
||||
if (flg & FHCRC)
|
||||
{
|
||||
/*unsigned int hcrc =*/ tinf_get_uint16(d);
|
||||
|
||||
// TODO: Check!
|
||||
// if (hcrc != (tinf_crc32(src, start - src) & 0x0000ffff))
|
||||
// return TINF_DATA_ERROR;
|
||||
}
|
||||
|
||||
/* initialize for crc32 checksum */
|
||||
d->checksum_type = TINF_CHKSUM_CRC;
|
||||
d->checksum = ~0;
|
||||
|
||||
return TINF_OK;
|
||||
}
|
@ -7,6 +7,9 @@
|
||||
*
|
||||
* Copyright (c) 2014-2018 by Paul Sokolovsky
|
||||
*
|
||||
* Optimised for MicroPython:
|
||||
* Copyright (c) 2023 by Jim Mussared
|
||||
*
|
||||
* This software is provided 'as-is', without any express
|
||||
* or implied warranty. In no event will the authors be
|
||||
* held liable for any damages arising from the use of
|
||||
@ -33,7 +36,7 @@
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "tinf.h"
|
||||
#include "uzlib.h"
|
||||
|
||||
#define UZLIB_DUMP_ARRAY(heading, arr, size) \
|
||||
{ \
|
||||
@ -44,52 +47,52 @@
|
||||
printf("\n"); \
|
||||
}
|
||||
|
||||
uint32_t tinf_get_le_uint32(TINF_DATA *d);
|
||||
uint32_t tinf_get_be_uint32(TINF_DATA *d);
|
||||
uint32_t tinf_get_le_uint32(uzlib_uncomp_t *d);
|
||||
uint32_t tinf_get_be_uint32(uzlib_uncomp_t *d);
|
||||
|
||||
/* --------------------------------------------------- *
|
||||
* -- uninitialized global data (static structures) -- *
|
||||
* --------------------------------------------------- */
|
||||
|
||||
#ifdef RUNTIME_BITS_TABLES
|
||||
typedef struct {
|
||||
unsigned char length_bits : 3;
|
||||
unsigned short length_base : 9;
|
||||
unsigned char dist_bits : 4;
|
||||
unsigned short dist_base : 15;
|
||||
} lookup_table_entry_t;
|
||||
|
||||
/* extra bits and base tables for length codes */
|
||||
unsigned char length_bits[30];
|
||||
unsigned short length_base[30];
|
||||
|
||||
/* extra bits and base tables for distance codes */
|
||||
unsigned char dist_bits[30];
|
||||
unsigned short dist_base[30];
|
||||
|
||||
#else
|
||||
|
||||
const unsigned char length_bits[30] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 4, 4, 4, 4,
|
||||
5, 5, 5, 5
|
||||
const lookup_table_entry_t lookup_table[30] = {
|
||||
{0, 3, 0, 1},
|
||||
{0, 4, 0, 2},
|
||||
{0, 5, 0, 3},
|
||||
{0, 6, 0, 4},
|
||||
{0, 7, 1, 5},
|
||||
{0, 8, 1, 7},
|
||||
{0, 9, 2, 9},
|
||||
{0, 10, 2, 13},
|
||||
{1, 11, 3, 17},
|
||||
{1, 13, 3, 25},
|
||||
{1, 15, 4, 33},
|
||||
{1, 17, 4, 49},
|
||||
{2, 19, 5, 65},
|
||||
{2, 23, 5, 97},
|
||||
{2, 27, 6, 129},
|
||||
{2, 31, 6, 193},
|
||||
{3, 35, 7, 257},
|
||||
{3, 43, 7, 385},
|
||||
{3, 51, 8, 513},
|
||||
{3, 59, 8, 769},
|
||||
{4, 67, 9, 1025},
|
||||
{4, 83, 9, 1537},
|
||||
{4, 99, 10, 2049},
|
||||
{4, 115, 10, 3073},
|
||||
{5, 131, 11, 4097},
|
||||
{5, 163, 11, 6145},
|
||||
{5, 195, 12, 8193},
|
||||
{5, 227, 12, 12289},
|
||||
{0, 258, 13, 16385},
|
||||
{0, 0, 13, 24577},
|
||||
};
|
||||
const unsigned short length_base[30] = {
|
||||
3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 13, 15, 17, 19, 23, 27, 31,
|
||||
35, 43, 51, 59, 67, 83, 99, 115,
|
||||
131, 163, 195, 227, 258
|
||||
};
|
||||
|
||||
const unsigned char dist_bits[30] = {
|
||||
0, 0, 0, 0, 1, 1, 2, 2,
|
||||
3, 3, 4, 4, 5, 5, 6, 6,
|
||||
7, 7, 8, 8, 9, 9, 10, 10,
|
||||
11, 11, 12, 12, 13, 13
|
||||
};
|
||||
const unsigned short dist_base[30] = {
|
||||
1, 2, 3, 4, 5, 7, 9, 13,
|
||||
17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073,
|
||||
4097, 6145, 8193, 12289, 16385, 24577
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* special ordering of code length codes */
|
||||
const unsigned char clcidx[] = {
|
||||
@ -102,25 +105,6 @@ const unsigned char clcidx[] = {
|
||||
* -- utility functions -- *
|
||||
* ----------------------- */
|
||||
|
||||
#ifdef RUNTIME_BITS_TABLES
|
||||
/* build extra bits and base tables */
|
||||
static void tinf_build_bits_base(unsigned char *bits, unsigned short *base, int delta, int first)
|
||||
{
|
||||
int i, sum;
|
||||
|
||||
/* build bits table */
|
||||
for (i = 0; i < delta; ++i) bits[i] = 0;
|
||||
for (i = 0; i < 30 - delta; ++i) bits[i + delta] = i / delta;
|
||||
|
||||
/* build base table */
|
||||
for (sum = first, i = 0; i < 30; ++i)
|
||||
{
|
||||
base[i] = sum;
|
||||
sum += 1 << bits[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* build the fixed huffman trees */
|
||||
static void tinf_build_fixed_trees(TINF_TREE *lt, TINF_TREE *dt)
|
||||
{
|
||||
@ -189,7 +173,7 @@ static void tinf_build_tree(TINF_TREE *t, const unsigned char *lengths, unsigned
|
||||
* -- decode functions -- *
|
||||
* ---------------------- */
|
||||
|
||||
unsigned char uzlib_get_byte(TINF_DATA *d)
|
||||
unsigned char uzlib_get_byte(uzlib_uncomp_t *d)
|
||||
{
|
||||
/* If end of source buffer is not reached, return next byte from source
|
||||
buffer. */
|
||||
@ -200,14 +184,14 @@ unsigned char uzlib_get_byte(TINF_DATA *d)
|
||||
/* Otherwise if there's callback and we haven't seen EOF yet, try to
|
||||
read next byte using it. (Note: the callback can also update ->source
|
||||
and ->source_limit). */
|
||||
if (d->readSource && !d->eof) {
|
||||
int val = d->readSource(d);
|
||||
if (d->source_read_cb && !d->eof) {
|
||||
int val = d->source_read_cb(d->source_read_data);
|
||||
if (val >= 0) {
|
||||
return (unsigned char)val;
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we hit EOF (either from ->readSource() or from exhaustion
|
||||
/* Otherwise, we hit EOF (either from ->source_read_cb() or from exhaustion
|
||||
of the buffer), and it will be "sticky", i.e. further calls to this
|
||||
function will end up here too. */
|
||||
d->eof = true;
|
||||
@ -215,7 +199,7 @@ unsigned char uzlib_get_byte(TINF_DATA *d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t tinf_get_le_uint32(TINF_DATA *d)
|
||||
uint32_t tinf_get_le_uint32(uzlib_uncomp_t *d)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
int i;
|
||||
@ -225,7 +209,7 @@ uint32_t tinf_get_le_uint32(TINF_DATA *d)
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t tinf_get_be_uint32(TINF_DATA *d)
|
||||
uint32_t tinf_get_be_uint32(uzlib_uncomp_t *d)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
int i;
|
||||
@ -236,7 +220,7 @@ uint32_t tinf_get_be_uint32(TINF_DATA *d)
|
||||
}
|
||||
|
||||
/* get one bit from source stream */
|
||||
static int tinf_getbit(TINF_DATA *d)
|
||||
static int tinf_getbit(uzlib_uncomp_t *d)
|
||||
{
|
||||
unsigned int bit;
|
||||
|
||||
@ -256,7 +240,7 @@ static int tinf_getbit(TINF_DATA *d)
|
||||
}
|
||||
|
||||
/* read a num bit value from a stream and add base */
|
||||
static unsigned int tinf_read_bits(TINF_DATA *d, int num, int base)
|
||||
static unsigned int tinf_read_bits(uzlib_uncomp_t *d, int num, int base)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
|
||||
@ -274,7 +258,7 @@ static unsigned int tinf_read_bits(TINF_DATA *d, int num, int base)
|
||||
}
|
||||
|
||||
/* given a data stream and a tree, decode a symbol */
|
||||
static int tinf_decode_symbol(TINF_DATA *d, TINF_TREE *t)
|
||||
static int tinf_decode_symbol(uzlib_uncomp_t *d, TINF_TREE *t)
|
||||
{
|
||||
int sum = 0, cur = 0, len = 0;
|
||||
|
||||
@ -284,7 +268,7 @@ static int tinf_decode_symbol(TINF_DATA *d, TINF_TREE *t)
|
||||
cur = 2*cur + tinf_getbit(d);
|
||||
|
||||
if (++len == TINF_ARRAY_SIZE(t->table)) {
|
||||
return TINF_DATA_ERROR;
|
||||
return UZLIB_DATA_ERROR;
|
||||
}
|
||||
|
||||
sum += t->table[len];
|
||||
@ -295,7 +279,7 @@ static int tinf_decode_symbol(TINF_DATA *d, TINF_TREE *t)
|
||||
sum += cur;
|
||||
#if UZLIB_CONF_PARANOID_CHECKS
|
||||
if (sum < 0 || sum >= TINF_ARRAY_SIZE(t->trans)) {
|
||||
return TINF_DATA_ERROR;
|
||||
return UZLIB_DATA_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -303,7 +287,7 @@ static int tinf_decode_symbol(TINF_DATA *d, TINF_TREE *t)
|
||||
}
|
||||
|
||||
/* given a data stream, decode dynamic trees from it */
|
||||
static int tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||
static int tinf_decode_trees(uzlib_uncomp_t *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||
{
|
||||
/* code lengths for 288 literal/len symbols and 32 dist symbols */
|
||||
unsigned char lengths[288+32];
|
||||
@ -348,7 +332,7 @@ static int tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||
{
|
||||
case 16:
|
||||
/* copy previous code length 3-6 times (read 2 bits) */
|
||||
if (num == 0) return TINF_DATA_ERROR;
|
||||
if (num == 0) return UZLIB_DATA_ERROR;
|
||||
fill_value = lengths[num - 1];
|
||||
lbits = 2;
|
||||
break;
|
||||
@ -370,7 +354,7 @@ static int tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||
|
||||
/* special code length 16-18 are handled here */
|
||||
length = tinf_read_bits(d, lbits, lbase);
|
||||
if (num + length > hlimit) return TINF_DATA_ERROR;
|
||||
if (num + length > hlimit) return UZLIB_DATA_ERROR;
|
||||
for (; length; --length)
|
||||
{
|
||||
lengths[num++] = fill_value;
|
||||
@ -387,7 +371,7 @@ static int tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||
#if UZLIB_CONF_PARANOID_CHECKS
|
||||
/* Check that there's "end of block" symbol */
|
||||
if (lengths[256] == 0) {
|
||||
return TINF_DATA_ERROR;
|
||||
return UZLIB_DATA_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -395,7 +379,7 @@ static int tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||
tinf_build_tree(lt, lengths, hlit);
|
||||
tinf_build_tree(dt, lengths + hlit, hdist);
|
||||
|
||||
return TINF_OK;
|
||||
return UZLIB_OK;
|
||||
}
|
||||
|
||||
/* ----------------------------- *
|
||||
@ -403,7 +387,7 @@ static int tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||
* ----------------------------- */
|
||||
|
||||
/* given a stream and two trees, inflate next byte of output */
|
||||
static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||
static int tinf_inflate_block_data(uzlib_uncomp_t *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||
{
|
||||
if (d->curlen == 0) {
|
||||
unsigned int offs;
|
||||
@ -412,41 +396,41 @@ static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||
//printf("huff sym: %02x\n", sym);
|
||||
|
||||
if (d->eof) {
|
||||
return TINF_DATA_ERROR;
|
||||
return UZLIB_DATA_ERROR;
|
||||
}
|
||||
|
||||
/* literal byte */
|
||||
if (sym < 256) {
|
||||
TINF_PUT(d, sym);
|
||||
return TINF_OK;
|
||||
return UZLIB_OK;
|
||||
}
|
||||
|
||||
/* end of block */
|
||||
if (sym == 256) {
|
||||
return TINF_DONE;
|
||||
return UZLIB_DONE;
|
||||
}
|
||||
|
||||
/* substring from sliding dictionary */
|
||||
sym -= 257;
|
||||
if (sym >= 29) {
|
||||
return TINF_DATA_ERROR;
|
||||
return UZLIB_DATA_ERROR;
|
||||
}
|
||||
|
||||
/* possibly get more bits from length code */
|
||||
d->curlen = tinf_read_bits(d, length_bits[sym], length_base[sym]);
|
||||
d->curlen = tinf_read_bits(d, lookup_table[sym].length_bits, lookup_table[sym].length_base);
|
||||
|
||||
dist = tinf_decode_symbol(d, dt);
|
||||
if (dist >= 30) {
|
||||
return TINF_DATA_ERROR;
|
||||
return UZLIB_DATA_ERROR;
|
||||
}
|
||||
|
||||
/* possibly get more bits from distance code */
|
||||
offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]);
|
||||
offs = tinf_read_bits(d, lookup_table[dist].dist_bits, lookup_table[dist].dist_base);
|
||||
|
||||
/* calculate and validate actual LZ offset to use */
|
||||
if (d->dict_ring) {
|
||||
if (offs > d->dict_size) {
|
||||
return TINF_DICT_ERROR;
|
||||
return UZLIB_DICT_ERROR;
|
||||
}
|
||||
/* Note: unlike full-dest-in-memory case below, we don't
|
||||
try to catch offset which points to not yet filled
|
||||
@ -464,8 +448,8 @@ static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||
}
|
||||
} else {
|
||||
/* catch trying to point before the start of dest buffer */
|
||||
if (offs > (unsigned int)(d->dest - d->destStart)) {
|
||||
return TINF_DATA_ERROR;
|
||||
if (offs > (unsigned int)(d->dest - d->dest_start)) {
|
||||
return UZLIB_DATA_ERROR;
|
||||
}
|
||||
d->lzOff = -offs;
|
||||
}
|
||||
@ -482,11 +466,11 @@ static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
|
||||
d->dest++;
|
||||
}
|
||||
d->curlen--;
|
||||
return TINF_OK;
|
||||
return UZLIB_OK;
|
||||
}
|
||||
|
||||
/* inflate next byte from uncompressed block of data */
|
||||
static int tinf_inflate_uncompressed_block(TINF_DATA *d)
|
||||
static int tinf_inflate_uncompressed_block(uzlib_uncomp_t *d)
|
||||
{
|
||||
if (d->curlen == 0) {
|
||||
unsigned int length, invlength;
|
||||
@ -498,9 +482,9 @@ static int tinf_inflate_uncompressed_block(TINF_DATA *d)
|
||||
invlength = uzlib_get_byte(d);
|
||||
invlength += 256 * uzlib_get_byte(d);
|
||||
/* check length */
|
||||
if (length != (~invlength & 0x0000ffff)) return TINF_DATA_ERROR;
|
||||
if (length != (~invlength & 0x0000ffff)) return UZLIB_DATA_ERROR;
|
||||
|
||||
/* increment length to properly return TINF_DONE below, without
|
||||
/* increment length to properly return UZLIB_DONE below, without
|
||||
producing data at the same time */
|
||||
d->curlen = length + 1;
|
||||
|
||||
@ -509,34 +493,20 @@ static int tinf_inflate_uncompressed_block(TINF_DATA *d)
|
||||
}
|
||||
|
||||
if (--d->curlen == 0) {
|
||||
return TINF_DONE;
|
||||
return UZLIB_DONE;
|
||||
}
|
||||
|
||||
unsigned char c = uzlib_get_byte(d);
|
||||
TINF_PUT(d, c);
|
||||
return TINF_OK;
|
||||
return UZLIB_OK;
|
||||
}
|
||||
|
||||
/* ---------------------- *
|
||||
* -- public functions -- *
|
||||
* ---------------------- */
|
||||
|
||||
/* initialize global (static) data */
|
||||
void uzlib_init(void)
|
||||
{
|
||||
#ifdef RUNTIME_BITS_TABLES
|
||||
/* build extra bits and base tables */
|
||||
tinf_build_bits_base(length_bits, length_base, 4, 3);
|
||||
tinf_build_bits_base(dist_bits, dist_base, 2, 1);
|
||||
|
||||
/* fix a special case */
|
||||
length_bits[28] = 0;
|
||||
length_base[28] = 258;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* initialize decompression structure */
|
||||
void uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen)
|
||||
void uzlib_uncompress_init(uzlib_uncomp_t *d, void *dict, unsigned int dictLen)
|
||||
{
|
||||
d->eof = 0;
|
||||
d->bitcount = 0;
|
||||
@ -549,7 +519,7 @@ void uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen)
|
||||
}
|
||||
|
||||
/* inflate next output bytes from compressed stream */
|
||||
int uzlib_uncompress(TINF_DATA *d)
|
||||
int uzlib_uncompress(uzlib_uncomp_t *d)
|
||||
{
|
||||
do {
|
||||
int res;
|
||||
@ -572,7 +542,7 @@ next_blk:
|
||||
} else if (d->btype == 2) {
|
||||
/* decode trees from stream */
|
||||
res = tinf_decode_trees(d, &d->ltree, &d->dtree);
|
||||
if (res != TINF_OK) {
|
||||
if (res != UZLIB_OK) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@ -592,27 +562,27 @@ next_blk:
|
||||
res = tinf_inflate_block_data(d, &d->ltree, &d->dtree);
|
||||
break;
|
||||
default:
|
||||
return TINF_DATA_ERROR;
|
||||
return UZLIB_DATA_ERROR;
|
||||
}
|
||||
|
||||
if (res == TINF_DONE && !d->bfinal) {
|
||||
if (res == UZLIB_DONE && !d->bfinal) {
|
||||
/* the block has ended (without producing more data), but we
|
||||
can't return without data, so start procesing next block */
|
||||
goto next_blk;
|
||||
}
|
||||
|
||||
if (res != TINF_OK) {
|
||||
if (res != UZLIB_OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
} while (d->dest < d->dest_limit);
|
||||
|
||||
return TINF_OK;
|
||||
return UZLIB_OK;
|
||||
}
|
||||
|
||||
/* inflate next output bytes from compressed stream, updating
|
||||
checksum, and at the end of stream, verify it */
|
||||
int uzlib_uncompress_chksum(TINF_DATA *d)
|
||||
int uzlib_uncompress_chksum(uzlib_uncomp_t *d)
|
||||
{
|
||||
int res;
|
||||
unsigned char *data = d->dest;
|
||||
@ -623,31 +593,31 @@ int uzlib_uncompress_chksum(TINF_DATA *d)
|
||||
|
||||
switch (d->checksum_type) {
|
||||
|
||||
case TINF_CHKSUM_ADLER:
|
||||
case UZLIB_CHKSUM_ADLER:
|
||||
d->checksum = uzlib_adler32(data, d->dest - data, d->checksum);
|
||||
break;
|
||||
|
||||
case TINF_CHKSUM_CRC:
|
||||
case UZLIB_CHKSUM_CRC:
|
||||
d->checksum = uzlib_crc32(data, d->dest - data, d->checksum);
|
||||
break;
|
||||
}
|
||||
|
||||
if (res == TINF_DONE) {
|
||||
if (res == UZLIB_DONE) {
|
||||
unsigned int val;
|
||||
|
||||
switch (d->checksum_type) {
|
||||
|
||||
case TINF_CHKSUM_ADLER:
|
||||
case UZLIB_CHKSUM_ADLER:
|
||||
val = tinf_get_be_uint32(d);
|
||||
if (d->checksum != val) {
|
||||
return TINF_CHKSUM_ERROR;
|
||||
return UZLIB_CHKSUM_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case TINF_CHKSUM_CRC:
|
||||
case UZLIB_CHKSUM_CRC:
|
||||
val = tinf_get_le_uint32(d);
|
||||
if (~d->checksum != val) {
|
||||
return TINF_CHKSUM_ERROR;
|
||||
return UZLIB_CHKSUM_ERROR;
|
||||
}
|
||||
// Uncompressed size. TODO: Check
|
||||
val = tinf_get_le_uint32(d);
|
||||
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* uzlib - tiny deflate/inflate library (deflate, gzip, zlib)
|
||||
*
|
||||
* Copyright (c) 2003 by Joergen Ibsen / Jibz
|
||||
* All Rights Reserved
|
||||
*
|
||||
* http://www.ibsensoftware.com/
|
||||
*
|
||||
* Copyright (c) 2014-2018 by Paul Sokolovsky
|
||||
*
|
||||
* This software is provided 'as-is', without any express
|
||||
* or implied warranty. In no event will the authors be
|
||||
* held liable for any damages arising from the use of
|
||||
* this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software
|
||||
* for any purpose, including commercial applications,
|
||||
* and to alter it and redistribute it freely, subject to
|
||||
* the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be
|
||||
* misrepresented; you must not claim that you
|
||||
* wrote the original software. If you use this
|
||||
* software in a product, an acknowledgment in
|
||||
* the product documentation would be appreciated
|
||||
* but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked
|
||||
* as such, and must not be misrepresented as
|
||||
* being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from
|
||||
* any source distribution.
|
||||
*/
|
||||
|
||||
#include "tinf.h"
|
||||
|
||||
int uzlib_zlib_parse_header(TINF_DATA *d)
|
||||
{
|
||||
unsigned char cmf, flg;
|
||||
|
||||
/* -- get header bytes -- */
|
||||
|
||||
cmf = uzlib_get_byte(d);
|
||||
flg = uzlib_get_byte(d);
|
||||
|
||||
/* -- check format -- */
|
||||
|
||||
/* check checksum */
|
||||
if ((256*cmf + flg) % 31) return TINF_DATA_ERROR;
|
||||
|
||||
/* check method is deflate */
|
||||
if ((cmf & 0x0f) != 8) return TINF_DATA_ERROR;
|
||||
|
||||
/* check window size is valid */
|
||||
if ((cmf >> 4) > 7) return TINF_DATA_ERROR;
|
||||
|
||||
/* check there is no preset dictionary */
|
||||
if (flg & 0x20) return TINF_DATA_ERROR;
|
||||
|
||||
/* initialize for adler32 checksum */
|
||||
d->checksum_type = TINF_CHKSUM_ADLER;
|
||||
d->checksum = 1;
|
||||
|
||||
return cmf >> 4;
|
||||
}
|
@ -7,6 +7,9 @@
|
||||
*
|
||||
* Copyright (c) 2014-2018 by Paul Sokolovsky
|
||||
*
|
||||
* Optimised for MicroPython:
|
||||
* Copyright (c) 2023 by Jim Mussared
|
||||
*
|
||||
* This software is provided 'as-is', without any express
|
||||
* or implied warranty. In no event will the authors be
|
||||
* held liable for any damages arising from the use of
|
||||
@ -39,38 +42,27 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "defl_static.h"
|
||||
|
||||
#include "uzlib_conf.h"
|
||||
#if UZLIB_CONF_DEBUG_LOG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/* calling convention */
|
||||
#ifndef TINFCC
|
||||
#ifdef __WATCOMC__
|
||||
#define TINFCC __cdecl
|
||||
#else
|
||||
#define TINFCC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ok status, more data produced */
|
||||
#define TINF_OK 0
|
||||
#define UZLIB_OK 0
|
||||
/* end of compressed stream reached */
|
||||
#define TINF_DONE 1
|
||||
#define TINF_DATA_ERROR (-3)
|
||||
#define TINF_CHKSUM_ERROR (-4)
|
||||
#define TINF_DICT_ERROR (-5)
|
||||
#define UZLIB_DONE 1
|
||||
#define UZLIB_DATA_ERROR (-3)
|
||||
#define UZLIB_CHKSUM_ERROR (-4)
|
||||
#define UZLIB_DICT_ERROR (-5)
|
||||
|
||||
/* checksum types */
|
||||
#define TINF_CHKSUM_NONE 0
|
||||
#define TINF_CHKSUM_ADLER 1
|
||||
#define TINF_CHKSUM_CRC 2
|
||||
#define UZLIB_CHKSUM_NONE 0
|
||||
#define UZLIB_CHKSUM_ADLER 1
|
||||
#define UZLIB_CHKSUM_CRC 2
|
||||
|
||||
/* helper macros */
|
||||
#define TINF_ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*(arr)))
|
||||
@ -82,9 +74,7 @@ typedef struct {
|
||||
unsigned short trans[288]; /* code -> symbol translation table */
|
||||
} TINF_TREE;
|
||||
|
||||
struct uzlib_uncomp {
|
||||
/* Point to the CircuitPython object that owns this decompression stream */
|
||||
void *self;
|
||||
typedef struct _uzlib_uncomp_t {
|
||||
/* Pointer to the next byte in the input buffer */
|
||||
const unsigned char *source;
|
||||
/* Pointer to the next byte past the input buffer (source_limit = source + len) */
|
||||
@ -94,7 +84,8 @@ struct uzlib_uncomp {
|
||||
also return -1 in case of EOF (or irrecoverable error). Note that
|
||||
besides returning the next byte, it may also update source and
|
||||
source_limit fields, thus allowing for buffered operation. */
|
||||
int (*source_read_cb)(struct uzlib_uncomp *uncomp);
|
||||
void *source_read_data;
|
||||
int (*source_read_cb)(void *);
|
||||
|
||||
unsigned int tag;
|
||||
unsigned int bitcount;
|
||||
@ -121,9 +112,7 @@ struct uzlib_uncomp {
|
||||
|
||||
TINF_TREE ltree; /* dynamic length/symbol tree */
|
||||
TINF_TREE dtree; /* dynamic distance tree */
|
||||
};
|
||||
|
||||
#include "tinf_compat.h"
|
||||
} uzlib_uncomp_t;
|
||||
|
||||
#define TINF_PUT(d, c) \
|
||||
{ \
|
||||
@ -131,38 +120,43 @@ struct uzlib_uncomp {
|
||||
if (d->dict_ring) { d->dict_ring[d->dict_idx++] = c; if (d->dict_idx == d->dict_size) d->dict_idx = 0; } \
|
||||
}
|
||||
|
||||
unsigned char TINFCC uzlib_get_byte(TINF_DATA *d);
|
||||
unsigned char uzlib_get_byte(uzlib_uncomp_t *d);
|
||||
|
||||
/* Decompression API */
|
||||
|
||||
void TINFCC uzlib_init(void);
|
||||
void TINFCC uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen);
|
||||
int TINFCC uzlib_uncompress(TINF_DATA *d);
|
||||
int TINFCC uzlib_uncompress_chksum(TINF_DATA *d);
|
||||
void uzlib_uncompress_init(uzlib_uncomp_t *d, void *dict, unsigned int dictLen);
|
||||
int uzlib_uncompress(uzlib_uncomp_t *d);
|
||||
int uzlib_uncompress_chksum(uzlib_uncomp_t *d);
|
||||
|
||||
int TINFCC uzlib_zlib_parse_header(TINF_DATA *d);
|
||||
int TINFCC uzlib_gzip_parse_header(TINF_DATA *d);
|
||||
#define UZLIB_HEADER_ZLIB 0
|
||||
#define UZLIB_HEADER_GZIP 1
|
||||
int uzlib_parse_zlib_gzip_header(uzlib_uncomp_t *d, int *wbits);
|
||||
|
||||
/* Compression API */
|
||||
|
||||
typedef const uint8_t *uzlib_hash_entry_t;
|
||||
typedef struct {
|
||||
void *dest_write_data;
|
||||
void (*dest_write_cb)(void *data, uint8_t byte);
|
||||
unsigned long outbits;
|
||||
int noutbits;
|
||||
uint8_t *hist_buf;
|
||||
size_t hist_max;
|
||||
size_t hist_start;
|
||||
size_t hist_len;
|
||||
} uzlib_lz77_state_t;
|
||||
|
||||
struct uzlib_comp {
|
||||
struct Outbuf out;
|
||||
void uzlib_lz77_init(uzlib_lz77_state_t *state, uint8_t *hist, size_t hist_max);
|
||||
void uzlib_lz77_compress(uzlib_lz77_state_t *state, const uint8_t *src, unsigned len);
|
||||
|
||||
uzlib_hash_entry_t *hash_table;
|
||||
unsigned int hash_bits;
|
||||
unsigned int dict_size;
|
||||
};
|
||||
|
||||
void TINFCC uzlib_compress(struct uzlib_comp *c, const uint8_t *src, unsigned slen);
|
||||
void uzlib_start_block(uzlib_lz77_state_t *state);
|
||||
void uzlib_finish_block(uzlib_lz77_state_t *state);
|
||||
|
||||
/* Checksum API */
|
||||
|
||||
/* prev_sum is previous value for incremental computation, 1 initially */
|
||||
uint32_t TINFCC uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum);
|
||||
uint32_t uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum);
|
||||
/* crc is previous value for incremental computation, 0xffffffff initially */
|
||||
uint32_t TINFCC uzlib_crc32(const void *data, unsigned int length, uint32_t crc);
|
||||
uint32_t uzlib_crc32(const void *data, unsigned int length, uint32_t crc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@ -48,6 +48,14 @@ mp_uint_t mp_verbose_flag = 0;
|
||||
// Make it larger on a 64 bit machine, because pointers are larger.
|
||||
long heap_size = 1024 * 1024 * (sizeof(mp_uint_t) / 4);
|
||||
|
||||
STATIC void stdout_print_strn(void *env, const char *str, size_t len) {
|
||||
(void)env;
|
||||
ssize_t dummy = write(STDOUT_FILENO, str, len);
|
||||
(void)dummy;
|
||||
}
|
||||
|
||||
STATIC const mp_print_t mp_stdout_print = {NULL, stdout_print_strn};
|
||||
|
||||
STATIC void stderr_print_strn(void *env, const char *str, size_t len) {
|
||||
(void)env;
|
||||
ssize_t dummy = write(STDERR_FILENO, str, len);
|
||||
@ -59,7 +67,12 @@ STATIC const mp_print_t mp_stderr_print = {NULL, stderr_print_strn};
|
||||
STATIC int compile_and_save(const char *file, const char *output_file, const char *source_file) {
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
mp_lexer_t *lex = mp_lexer_new_from_file(file);
|
||||
mp_lexer_t *lex;
|
||||
if (strcmp(file, "-") == 0) {
|
||||
lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, STDIN_FILENO, false);
|
||||
} else {
|
||||
lex = mp_lexer_new_from_file(file);
|
||||
}
|
||||
|
||||
qstr source_name;
|
||||
if (source_file == NULL) {
|
||||
@ -77,6 +90,10 @@ STATIC int compile_and_save(const char *file, const char *output_file, const cha
|
||||
cm.context = m_new_obj(mp_module_context_t);
|
||||
mp_compile_to_raw_code(&parse_tree, source_name, false, &cm);
|
||||
|
||||
if ((output_file != NULL && strcmp(output_file, "-") == 0) ||
|
||||
(output_file == NULL && strcmp(file, "-") == 0)) {
|
||||
mp_raw_code_save(&cm, (mp_print_t *)&mp_stdout_print);
|
||||
} else {
|
||||
vstr_t vstr;
|
||||
vstr_init(&vstr, 16);
|
||||
if (output_file == NULL) {
|
||||
@ -86,8 +103,10 @@ STATIC int compile_and_save(const char *file, const char *output_file, const cha
|
||||
} else {
|
||||
vstr_add_str(&vstr, output_file);
|
||||
}
|
||||
|
||||
mp_raw_code_save_file(&cm, vstr_null_terminated_str(&vstr));
|
||||
vstr_clear(&vstr);
|
||||
}
|
||||
|
||||
nlr_pop();
|
||||
return 0;
|
||||
@ -100,10 +119,10 @@ STATIC int compile_and_save(const char *file, const char *output_file, const cha
|
||||
|
||||
STATIC int usage(char **argv) {
|
||||
printf(
|
||||
"usage: %s [<opts>] [-X <implopt>] <input filename>\n"
|
||||
"usage: %s [<opts>] [-X <implopt>] [--] <input filename>\n"
|
||||
"Options:\n"
|
||||
"--version : show version information\n"
|
||||
"-o : output file for compiled bytecode (defaults to input with .mpy extension)\n"
|
||||
"-o : output file for compiled bytecode (defaults to input filename with .mpy extension, or stdout if input is stdin)\n"
|
||||
"-s : source filename to embed in the compiled bytecode (defaults to input file)\n"
|
||||
"-v : verbose (trace various operations); can be multiple\n"
|
||||
"-O[N] : apply bytecode optimizations of level N\n"
|
||||
@ -220,10 +239,11 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
const char *input_file = NULL;
|
||||
const char *output_file = NULL;
|
||||
const char *source_file = NULL;
|
||||
bool option_parsing_active = true;
|
||||
|
||||
// parse main options
|
||||
for (int a = 1; a < argc; a++) {
|
||||
if (argv[a][0] == '-') {
|
||||
if (option_parsing_active && argv[a][0] == '-' && argv[a][1] != '\0') {
|
||||
if (strcmp(argv[a], "-X") == 0) {
|
||||
a += 1;
|
||||
} else if (strcmp(argv[a], "--version") == 0) {
|
||||
@ -309,6 +329,8 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
} else {
|
||||
return usage(argv);
|
||||
}
|
||||
} else if (strcmp(argv[a], "--") == 0) {
|
||||
option_parsing_active = false;
|
||||
} else {
|
||||
return usage(argv);
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ def compile(src, dest=None, src_path=None, opt=None, march=None, mpy_cross=None,
|
||||
if not src:
|
||||
raise ValueError("src is required")
|
||||
if not os.path.exists(src):
|
||||
raise CrossCompileError("Input .py file not found: {}.".format(src_py))
|
||||
raise CrossCompileError("Input .py file not found: {}.".format(src))
|
||||
|
||||
args = []
|
||||
|
||||
|
@ -178,7 +178,7 @@ void clocks_init(void) {
|
||||
CLOCK_DisableClock(kCLOCK_Lpuart3);
|
||||
CLOCK_DisableClock(kCLOCK_Lpuart4);
|
||||
/* Set UART_CLK_PODF. */
|
||||
CLOCK_SetDiv(kCLOCK_UartDiv, 0);
|
||||
CLOCK_SetDiv(kCLOCK_UartDiv, 1);
|
||||
/* Set Uart clock source. */
|
||||
CLOCK_SetMux(kCLOCK_UartMux, 0);
|
||||
/* Disable SPDIF clock gate. */
|
||||
|
@ -213,7 +213,7 @@ void clocks_init(void) {
|
||||
CLOCK_DisableClock(kCLOCK_Lpuart3);
|
||||
CLOCK_DisableClock(kCLOCK_Lpuart4);
|
||||
/* Set UART_CLK_PODF. */
|
||||
CLOCK_SetDiv(kCLOCK_UartDiv, 0);
|
||||
CLOCK_SetDiv(kCLOCK_UartDiv, 1);
|
||||
/* Set Uart clock source. */
|
||||
CLOCK_SetMux(kCLOCK_UartMux, 0);
|
||||
/* Disable SPDIF clock gate. */
|
||||
|
@ -246,7 +246,7 @@ void clocks_init(void) {
|
||||
CLOCK_DisableClock(kCLOCK_Lpuart7);
|
||||
CLOCK_DisableClock(kCLOCK_Lpuart8);
|
||||
/* Set UART_CLK_PODF. */
|
||||
CLOCK_SetDiv(kCLOCK_UartDiv, 0);
|
||||
CLOCK_SetDiv(kCLOCK_UartDiv, 1);
|
||||
/* Set Uart clock source. */
|
||||
CLOCK_SetMux(kCLOCK_UartMux, 0);
|
||||
/* Disable SPDIF clock gate. */
|
||||
|
@ -224,7 +224,7 @@ void clocks_init(void) {
|
||||
CLOCK_DisableClock(kCLOCK_Lpuart7);
|
||||
CLOCK_DisableClock(kCLOCK_Lpuart8);
|
||||
/* Set UART_CLK_PODF. */
|
||||
CLOCK_SetDiv(kCLOCK_UartDiv, 0);
|
||||
CLOCK_SetDiv(kCLOCK_UartDiv, 1);
|
||||
/* Set Uart clock source. */
|
||||
CLOCK_SetMux(kCLOCK_UartMux, 0);
|
||||
/* Disable LCDIF clock gate. */
|
||||
|
@ -231,7 +231,7 @@ void clocks_init(void) {
|
||||
CLOCK_DisableClock(kCLOCK_Lpuart7);
|
||||
CLOCK_DisableClock(kCLOCK_Lpuart8);
|
||||
/* Set UART_CLK_PODF. */
|
||||
CLOCK_SetDiv(kCLOCK_UartDiv, 0);
|
||||
CLOCK_SetDiv(kCLOCK_UartDiv, 1);
|
||||
/* Set Uart clock source. */
|
||||
CLOCK_SetMux(kCLOCK_UartMux, 0);
|
||||
/* Disable LCDIF clock gate. */
|
||||
|
@ -27,8 +27,8 @@ FROZEN_MANIFEST ?= variants/manifest.py
|
||||
PROG ?= micropython
|
||||
|
||||
# qstr definitions (must come before including py.mk)
|
||||
QSTR_DEFS = qstrdefsport.h
|
||||
QSTR_GLOBAL_DEPENDENCIES = $(VARIANT_DIR)/mpconfigvariant.h
|
||||
QSTR_DEFS += qstrdefsport.h
|
||||
QSTR_GLOBAL_DEPENDENCIES += $(VARIANT_DIR)/mpconfigvariant.h
|
||||
|
||||
# OS name, for simple autoconfig
|
||||
UNAME_S := $(shell uname -s)
|
||||
@ -59,8 +59,8 @@ endif
|
||||
# Remove unused sections.
|
||||
COPT += -fdata-sections -ffunction-sections
|
||||
|
||||
# Always enable symbols -- They're occasionally useful, and don't make it into the
|
||||
# final .bin/.hex/.dfu so the extra size doesn't matter.
|
||||
# Note: Symbols and debug information will still be stripped from the final binary
|
||||
# unless "DEBUG=1" or "STRIP=" is passed to make, see README.md for details.
|
||||
CFLAGS += -g
|
||||
|
||||
ifndef DEBUG
|
||||
@ -138,7 +138,7 @@ CFLAGS += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0
|
||||
LDFLAGS += $(LIBPTHREAD)
|
||||
endif
|
||||
|
||||
ifeq ($(MICROPY_PY_USSL),1)
|
||||
ifeq ($(MICROPY_PY_SSL),1)
|
||||
ifeq ($(MICROPY_SSL_AXTLS),1)
|
||||
|
||||
endif
|
||||
|
@ -40,8 +40,8 @@ or
|
||||
>>> import mip
|
||||
>>> mip.install("hmac")
|
||||
|
||||
Browse available modules at [micropython-lib]
|
||||
(https://github.com/micropython/micropython-lib). See
|
||||
Browse available modules at
|
||||
[micropython-lib](https://github.com/micropython/micropython-lib). See
|
||||
[Package management](https://docs.micropython.org/en/latest/reference/packages.html)
|
||||
for more information about `mip`.
|
||||
|
||||
@ -70,5 +70,19 @@ or not). If you intend to build MicroPython with additional options
|
||||
(like cross-compiling), the same set of options should be passed to `make
|
||||
deplibs`. To actually enable/disable use of dependencies, edit the
|
||||
`ports/unix/mpconfigport.mk` file, which has inline descriptions of the
|
||||
options. For example, to build the SSL module, `MICROPY_PY_USSL` should be
|
||||
options. For example, to build the SSL module, `MICROPY_PY_SSL` should be
|
||||
set to 1.
|
||||
|
||||
Debug Symbols
|
||||
-------------
|
||||
|
||||
By default, builds are stripped of symbols and debug information to save size.
|
||||
|
||||
To build a debuggable version of the Unix port, there are two options
|
||||
|
||||
1. Run `make [other arguments] DEBUG=1`. Note setting `DEBUG` also reduces the
|
||||
optimisation level, so it's not a good option for builds that also want the
|
||||
best performance.
|
||||
2. Run `make [other arguments] STRIP=`. Note that the value of `STRIP` is
|
||||
empty. This will skip the build step that strips symbols and debug
|
||||
information, but changes nothing else in the build configuration.
|
||||
|
@ -48,7 +48,7 @@
|
||||
#include "py/mphal.h"
|
||||
#include "py/mpthread.h"
|
||||
#include "extmod/misc.h"
|
||||
#include "extmod/moduplatform.h"
|
||||
#include "extmod/modplatform.h"
|
||||
#include "extmod/vfs.h"
|
||||
#include "extmod/vfs_posix.h"
|
||||
#include "genhdr/mpversion.h"
|
||||
@ -69,12 +69,20 @@ long heap_size = 1024 * 1024 * (sizeof(mp_uint_t) / 4);
|
||||
#define MICROPY_GC_SPLIT_HEAP_N_HEAPS (1)
|
||||
#endif
|
||||
|
||||
#if !MICROPY_PY_SYS_PATH
|
||||
#error "The unix port requires MICROPY_PY_SYS_PATH=1"
|
||||
#endif
|
||||
|
||||
#if !MICROPY_PY_SYS_ARGV
|
||||
#error "The unix port requires MICROPY_PY_SYS_ARGV=1"
|
||||
#endif
|
||||
|
||||
STATIC void stderr_print_strn(void *env, const char *str, size_t len) {
|
||||
(void)env;
|
||||
ssize_t ret;
|
||||
MP_HAL_RETRY_SYSCALL(ret, write(STDERR_FILENO, str, len), {});
|
||||
#if MICROPY_PY_OS_DUPTERM
|
||||
mp_uos_dupterm_tx_strn(str, len);
|
||||
mp_os_dupterm_tx_strn(str, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -540,44 +548,40 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
// sys.path starts as [""]
|
||||
mp_sys_path = mp_obj_new_list(0, NULL);
|
||||
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_));
|
||||
|
||||
// Add colon-separated entries from MICROPYPATH.
|
||||
char *home = getenv("HOME");
|
||||
char *path = getenv("MICROPYPATH");
|
||||
if (path == NULL) {
|
||||
path = MICROPY_PY_SYS_PATH_DEFAULT;
|
||||
}
|
||||
size_t path_num = 1; // [0] is for current dir (or base dir of the script)
|
||||
if (*path == PATHLIST_SEP_CHAR) {
|
||||
path_num++;
|
||||
// First entry is empty. We've already added an empty entry to sys.path, so skip it.
|
||||
++path;
|
||||
}
|
||||
for (char *p = path; p != NULL; p = strchr(p, PATHLIST_SEP_CHAR)) {
|
||||
path_num++;
|
||||
if (p != NULL) {
|
||||
p++;
|
||||
bool path_remaining = *path;
|
||||
while (path_remaining) {
|
||||
char *path_entry_end = strchr(path, PATHLIST_SEP_CHAR);
|
||||
if (path_entry_end == NULL) {
|
||||
path_entry_end = path + strlen(path);
|
||||
path_remaining = false;
|
||||
}
|
||||
}
|
||||
mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), path_num);
|
||||
mp_obj_t *path_items;
|
||||
mp_obj_list_get(mp_sys_path, &path_num, &path_items);
|
||||
path_items[0] = MP_OBJ_NEW_QSTR(MP_QSTR_);
|
||||
{
|
||||
char *p = path;
|
||||
for (mp_uint_t i = 1; i < path_num; i++) {
|
||||
char *p1 = strchr(p, PATHLIST_SEP_CHAR);
|
||||
if (p1 == NULL) {
|
||||
p1 = p + strlen(p);
|
||||
}
|
||||
if (p[0] == '~' && p[1] == '/' && home != NULL) {
|
||||
if (path[0] == '~' && path[1] == '/' && home != NULL) {
|
||||
// Expand standalone ~ to $HOME
|
||||
int home_l = strlen(home);
|
||||
vstr_t vstr;
|
||||
vstr_init(&vstr, home_l + (p1 - p - 1) + 1);
|
||||
vstr_init(&vstr, home_l + (path_entry_end - path - 1) + 1);
|
||||
vstr_add_strn(&vstr, home, home_l);
|
||||
vstr_add_strn(&vstr, p + 1, p1 - p - 1);
|
||||
path_items[i] = mp_obj_new_str_from_vstr(&vstr);
|
||||
vstr_add_strn(&vstr, path + 1, path_entry_end - path - 1);
|
||||
mp_obj_list_append(mp_sys_path, mp_obj_new_str_from_vstr(&vstr));
|
||||
} else {
|
||||
path_items[i] = mp_obj_new_str_via_qstr(p, p1 - p);
|
||||
mp_obj_list_append(mp_sys_path, mp_obj_new_str_via_qstr(path, path_entry_end - path));
|
||||
}
|
||||
p = p1 + 1;
|
||||
path = path_entry_end + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -666,7 +670,10 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
return handle_uncaught_exception(nlr.ret_val) & 0xff;
|
||||
}
|
||||
|
||||
if (mp_obj_is_package(mod) && !subpkg_tried) {
|
||||
// If this module is a package, see if it has a `__main__.py`.
|
||||
mp_obj_t dest[2];
|
||||
mp_load_method_protected(mod, MP_QSTR___path__, dest, true);
|
||||
if (dest[0] != MP_OBJ_NULL && !subpkg_tried) {
|
||||
subpkg_tried = true;
|
||||
vstr_t vstr;
|
||||
int len = strlen(argv[a + 1]);
|
||||
@ -709,7 +716,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
|
||||
// Set base dir of the script as first entry in sys.path.
|
||||
char *p = strrchr(basedir, '/');
|
||||
path_items[0] = mp_obj_new_str_via_qstr(basedir, p - basedir);
|
||||
mp_obj_list_store(mp_sys_path, MP_OBJ_NEW_SMALL_INT(0), mp_obj_new_str_via_qstr(basedir, p - basedir));
|
||||
free(pathbuf);
|
||||
|
||||
set_sys_argv(argv, argc, a);
|
||||
|
@ -27,7 +27,7 @@
|
||||
#define MICROPY_INCLUDED_MBEDTLS_CONFIG_H
|
||||
|
||||
// Set mbedtls configuration
|
||||
#define MBEDTLS_CIPHER_MODE_CTR // needed for MICROPY_PY_UCRYPTOLIB_CTR
|
||||
#define MBEDTLS_CIPHER_MODE_CTR // needed for MICROPY_PY_CRYPTOLIB_CTR
|
||||
|
||||
// Enable mbedtls modules
|
||||
#define MBEDTLS_HAVEGE_C
|
||||
|
@ -329,8 +329,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
unary_op, jobject_unary_op,
|
||||
attr, jobject_attr,
|
||||
subscr, jobject_subscr,
|
||||
iter, subscr_getiter,
|
||||
// .locals_dict = &jobject_locals_dict,
|
||||
iter, subscr_getiter
|
||||
);
|
||||
|
||||
STATIC mp_obj_t new_jobject(jobject jo) {
|
||||
@ -574,9 +573,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
MP_QSTR_jmethod,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
print, jmethod_print,
|
||||
call, jmethod_call,
|
||||
// .attr = jobject_attr,
|
||||
// .locals_dict = &jobject_locals_dict,
|
||||
call, jmethod_call
|
||||
);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
@ -615,26 +612,26 @@ STATIC void create_jvm(void) {
|
||||
|
||||
jclass Object_class = JJ(FindClass, "java/lang/Object");
|
||||
Object_toString_mid = JJ(GetMethodID, Object_class, "toString",
|
||||
MP_ERROR_TEXT("()Ljava/lang/String;"));
|
||||
MP_COMPRESSED_ROM_TEXT("()Ljava/lang/String;"));
|
||||
|
||||
Class_getName_mid = (*env)->GetMethodID(env, Class_class, "getName",
|
||||
MP_ERROR_TEXT("()Ljava/lang/String;"));
|
||||
MP_COMPRESSED_ROM_TEXT("()Ljava/lang/String;"));
|
||||
Class_getField_mid = (*env)->GetMethodID(env, Class_class, "getField",
|
||||
MP_ERROR_TEXT("(Ljava/lang/String;)Ljava/lang/reflect/Field;"));
|
||||
MP_COMPRESSED_ROM_TEXT("(Ljava/lang/String;)Ljava/lang/reflect/Field;"));
|
||||
Class_getMethods_mid = (*env)->GetMethodID(env, Class_class, "getMethods",
|
||||
MP_ERROR_TEXT("()[Ljava/lang/reflect/Method;"));
|
||||
MP_COMPRESSED_ROM_TEXT("()[Ljava/lang/reflect/Method;"));
|
||||
Class_getConstructors_mid = (*env)->GetMethodID(env, Class_class, "getConstructors",
|
||||
MP_ERROR_TEXT("()[Ljava/lang/reflect/Constructor;"));
|
||||
MP_COMPRESSED_ROM_TEXT("()[Ljava/lang/reflect/Constructor;"));
|
||||
Method_getName_mid = (*env)->GetMethodID(env, method_class, "getName",
|
||||
MP_ERROR_TEXT("()Ljava/lang/String;"));
|
||||
MP_COMPRESSED_ROM_TEXT("()Ljava/lang/String;"));
|
||||
|
||||
List_class = JJ(FindClass, "java/util/List");
|
||||
List_get_mid = JJ(GetMethodID, List_class, "get",
|
||||
MP_ERROR_TEXT("(I)Ljava/lang/Object;"));
|
||||
MP_COMPRESSED_ROM_TEXT("(I)Ljava/lang/Object;"));
|
||||
List_set_mid = JJ(GetMethodID, List_class, "set",
|
||||
MP_ERROR_TEXT("(ILjava/lang/Object;)Ljava/lang/Object;"));
|
||||
MP_COMPRESSED_ROM_TEXT("(ILjava/lang/Object;)Ljava/lang/Object;"));
|
||||
List_size_mid = JJ(GetMethodID, List_class, "size",
|
||||
MP_ERROR_TEXT("()I"));
|
||||
MP_COMPRESSED_ROM_TEXT("()I"));
|
||||
IndexException_class = JJ(FindClass, "java/lang/IndexOutOfBoundsException");
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
|
||||
@ -110,6 +110,6 @@ const mp_obj_module_t mp_module_machine = {
|
||||
.globals = (mp_obj_dict_t *)&machine_module_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_umachine, mp_module_machine);
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_machine, mp_module_machine);
|
||||
|
||||
#endif // MICROPY_PY_MACHINE
|
||||
|
@ -40,7 +40,7 @@ os_getenv_err_t common_hal_os_getenv_str(const char *key, char *value, size_t va
|
||||
os_getenv_err_t common_hal_os_getenv_int(const char *key, mp_int_t *value);
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t mp_uos_getenv(size_t n_args, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t mp_os_getenv(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_t var_in = args[0];
|
||||
#if defined(MICROPY_UNIX_COVERAGE)
|
||||
mp_obj_t result = common_hal_os_getenv(mp_obj_str_get_str(var_in), mp_const_none);
|
||||
@ -50,14 +50,18 @@ STATIC mp_obj_t mp_uos_getenv(size_t n_args, const mp_obj_t *args) {
|
||||
#endif
|
||||
const char *s = getenv(mp_obj_str_get_str(var_in));
|
||||
if (s == NULL) {
|
||||
return n_args > 1 ? args[1] : mp_const_none;
|
||||
if (n_args == 2) {
|
||||
return args[1];
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
return mp_obj_new_str(s, strlen(s));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_getenv_obj, 1, 2, mp_uos_getenv);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_os_getenv_obj, 1, 2, mp_os_getenv);
|
||||
|
||||
// CIRCUITPY getenv differences
|
||||
#if defined(MICROPY_UNIX_COVERAGE)
|
||||
STATIC mp_obj_t mp_uos_getenv_int(mp_obj_t var_in) {
|
||||
STATIC mp_obj_t mp_os_getenv_int(mp_obj_t var_in) {
|
||||
mp_int_t value;
|
||||
os_getenv_err_t result = common_hal_os_getenv_int(mp_obj_str_get_str(var_in), &value);
|
||||
if (result == 0) {
|
||||
@ -65,9 +69,9 @@ STATIC mp_obj_t mp_uos_getenv_int(mp_obj_t var_in) {
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_getenv_int_obj, mp_uos_getenv_int);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_os_getenv_int_obj, mp_os_getenv_int);
|
||||
|
||||
STATIC mp_obj_t mp_uos_getenv_str(mp_obj_t var_in) {
|
||||
STATIC mp_obj_t mp_os_getenv_str(mp_obj_t var_in) {
|
||||
char buf[4096];
|
||||
os_getenv_err_t result = common_hal_os_getenv_str(mp_obj_str_get_str(var_in), buf, sizeof(buf));
|
||||
if (result == 0) {
|
||||
@ -75,10 +79,10 @@ STATIC mp_obj_t mp_uos_getenv_str(mp_obj_t var_in) {
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_getenv_str_obj, mp_uos_getenv_str);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_os_getenv_str_obj, mp_os_getenv_str);
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t mp_uos_putenv(mp_obj_t key_in, mp_obj_t value_in) {
|
||||
STATIC mp_obj_t mp_os_putenv(mp_obj_t key_in, mp_obj_t value_in) {
|
||||
const char *key = mp_obj_str_get_str(key_in);
|
||||
const char *value = mp_obj_str_get_str(value_in);
|
||||
int ret;
|
||||
@ -94,9 +98,9 @@ STATIC mp_obj_t mp_uos_putenv(mp_obj_t key_in, mp_obj_t value_in) {
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_uos_putenv_obj, mp_uos_putenv);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_os_putenv_obj, mp_os_putenv);
|
||||
|
||||
STATIC mp_obj_t mp_uos_unsetenv(mp_obj_t key_in) {
|
||||
STATIC mp_obj_t mp_os_unsetenv(mp_obj_t key_in) {
|
||||
const char *key = mp_obj_str_get_str(key_in);
|
||||
int ret;
|
||||
|
||||
@ -111,9 +115,9 @@ STATIC mp_obj_t mp_uos_unsetenv(mp_obj_t key_in) {
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_unsetenv_obj, mp_uos_unsetenv);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_unsetenv_obj, mp_os_unsetenv);
|
||||
|
||||
STATIC mp_obj_t mp_uos_system(mp_obj_t cmd_in) {
|
||||
STATIC mp_obj_t mp_os_system(mp_obj_t cmd_in) {
|
||||
const char *cmd = mp_obj_str_get_str(cmd_in);
|
||||
|
||||
MP_THREAD_GIL_EXIT();
|
||||
@ -124,18 +128,18 @@ STATIC mp_obj_t mp_uos_system(mp_obj_t cmd_in) {
|
||||
|
||||
return MP_OBJ_NEW_SMALL_INT(r);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_system_obj, mp_uos_system);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_system_obj, mp_os_system);
|
||||
|
||||
STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) {
|
||||
STATIC mp_obj_t mp_os_urandom(mp_obj_t num) {
|
||||
mp_int_t n = mp_obj_get_int(num);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, n);
|
||||
mp_hal_get_random(n, vstr.buf);
|
||||
return mp_obj_new_bytes_from_vstr(&vstr);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_urandom_obj, mp_os_urandom);
|
||||
|
||||
STATIC mp_obj_t mp_uos_errno(size_t n_args, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t mp_os_errno(size_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0) {
|
||||
return MP_OBJ_NEW_SMALL_INT(errno);
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2017 Paul Sokolovsky
|
||||
* Copyright (c) 2014-2017 Damien P. George
|
||||
* Copyright (c) 2014-2023 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -25,9 +25,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#if MICROPY_PY_UTIME
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
@ -35,10 +32,8 @@
|
||||
#include <sys/time.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/smallint.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/utime_mphal.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
static inline int msec_sleep_tv(struct timeval *tv) {
|
||||
@ -66,7 +61,7 @@ static inline int msec_sleep_tv(struct timeval *tv) {
|
||||
#error Unsupported clock() implementation
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t mod_time_time(void) {
|
||||
STATIC mp_obj_t mp_time_time_get(void) {
|
||||
#if MICROPY_PY_BUILTINS_FLOAT && MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
@ -91,7 +86,7 @@ STATIC mp_obj_t mod_time_clock(void) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_clock_obj, mod_time_clock);
|
||||
|
||||
STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) {
|
||||
STATIC mp_obj_t mp_time_sleep(mp_obj_t arg) {
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
struct timeval tv;
|
||||
mp_float_t val = mp_obj_get_float(arg);
|
||||
|
@ -1,356 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Damien P. George
|
||||
* Copyright (c) 2015-2017 Paul Sokolovsky
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
|
||||
#if MICROPY_PY_USELECT_POSIX
|
||||
|
||||
#if MICROPY_PY_USELECT
|
||||
#error "Can't have both MICROPY_PY_USELECT and MICROPY_PY_USELECT_POSIX."
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/objlist.h"
|
||||
#include "py/objtuple.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/mpthread.h"
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
#if MICROPY_PY_SOCKET
|
||||
extern const mp_obj_type_t mp_type_socket;
|
||||
#endif
|
||||
|
||||
// Flags for poll()
|
||||
#define FLAG_ONESHOT (1)
|
||||
|
||||
/// \class Poll - poll class
|
||||
|
||||
typedef struct _mp_obj_poll_t {
|
||||
mp_obj_base_t base;
|
||||
unsigned short alloc;
|
||||
unsigned short len;
|
||||
struct pollfd *entries;
|
||||
mp_obj_t *obj_map;
|
||||
short iter_cnt;
|
||||
short iter_idx;
|
||||
int flags;
|
||||
// callee-owned tuple
|
||||
mp_obj_t ret_tuple;
|
||||
} mp_obj_poll_t;
|
||||
|
||||
STATIC int get_fd(mp_obj_t fdlike) {
|
||||
if (mp_obj_is_obj(fdlike)) {
|
||||
const mp_stream_p_t *stream_p = mp_get_stream_raise(fdlike, MP_STREAM_OP_IOCTL);
|
||||
int err;
|
||||
mp_uint_t res = stream_p->ioctl(fdlike, MP_STREAM_GET_FILENO, 0, &err);
|
||||
if (res != MP_STREAM_ERROR) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return mp_obj_get_int(fdlike);
|
||||
}
|
||||
|
||||
/// \method register(obj[, eventmask])
|
||||
STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
bool is_fd = mp_obj_is_int(args[1]);
|
||||
int fd = get_fd(args[1]);
|
||||
|
||||
mp_uint_t flags;
|
||||
if (n_args == 3) {
|
||||
flags = mp_obj_get_int(args[2]);
|
||||
} else {
|
||||
flags = POLLIN | POLLOUT;
|
||||
}
|
||||
|
||||
struct pollfd *free_slot = NULL;
|
||||
|
||||
struct pollfd *entry = self->entries;
|
||||
for (int i = 0; i < self->len; i++, entry++) {
|
||||
int entry_fd = entry->fd;
|
||||
if (entry_fd == fd) {
|
||||
entry->events = flags;
|
||||
return mp_const_false;
|
||||
}
|
||||
if (entry_fd == -1) {
|
||||
free_slot = entry;
|
||||
}
|
||||
}
|
||||
|
||||
if (free_slot == NULL) {
|
||||
if (self->len >= self->alloc) {
|
||||
self->entries = m_renew(struct pollfd, self->entries, self->alloc, self->alloc + 4);
|
||||
if (self->obj_map) {
|
||||
self->obj_map = m_renew(mp_obj_t, self->obj_map, self->alloc, self->alloc + 4);
|
||||
}
|
||||
self->alloc += 4;
|
||||
}
|
||||
free_slot = &self->entries[self->len++];
|
||||
}
|
||||
|
||||
if (!is_fd) {
|
||||
if (self->obj_map == NULL) {
|
||||
self->obj_map = m_new0(mp_obj_t, self->alloc);
|
||||
}
|
||||
self->obj_map[free_slot - self->entries] = args[1];
|
||||
}
|
||||
|
||||
free_slot->fd = fd;
|
||||
free_slot->events = flags;
|
||||
free_slot->revents = 0;
|
||||
return mp_const_true;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register);
|
||||
|
||||
/// \method unregister(obj)
|
||||
STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
struct pollfd *entries = self->entries;
|
||||
int fd = get_fd(obj_in);
|
||||
for (int i = self->len - 1; i >= 0; i--) {
|
||||
if (entries->fd == fd) {
|
||||
entries->fd = -1;
|
||||
if (self->obj_map) {
|
||||
self->obj_map[entries - self->entries] = MP_OBJ_NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
entries++;
|
||||
}
|
||||
|
||||
// TODO raise KeyError if obj didn't exist in map
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister);
|
||||
|
||||
/// \method modify(obj, eventmask)
|
||||
STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
struct pollfd *entries = self->entries;
|
||||
int fd = get_fd(obj_in);
|
||||
for (int i = self->len - 1; i >= 0; i--) {
|
||||
if (entries->fd == fd) {
|
||||
entries->events = mp_obj_get_int(eventmask_in);
|
||||
return mp_const_none;
|
||||
}
|
||||
entries++;
|
||||
}
|
||||
|
||||
// obj doesn't exist in poller
|
||||
mp_raise_OSError(MP_ENOENT);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify);
|
||||
|
||||
STATIC int poll_poll_internal(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
// work out timeout (it's given already in ms)
|
||||
int timeout = -1;
|
||||
int flags = 0;
|
||||
if (n_args >= 2) {
|
||||
if (args[1] != mp_const_none) {
|
||||
mp_int_t timeout_i = mp_obj_get_int(args[1]);
|
||||
if (timeout_i >= 0) {
|
||||
timeout = timeout_i;
|
||||
}
|
||||
}
|
||||
if (n_args >= 3) {
|
||||
flags = mp_obj_get_int(args[2]);
|
||||
}
|
||||
}
|
||||
|
||||
self->flags = flags;
|
||||
|
||||
int n_ready;
|
||||
MP_HAL_RETRY_SYSCALL(n_ready, poll(self->entries, self->len, timeout), mp_raise_OSError(err));
|
||||
return n_ready;
|
||||
}
|
||||
|
||||
/// \method poll([timeout])
|
||||
/// Timeout is in milliseconds.
|
||||
STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) {
|
||||
int n_ready = poll_poll_internal(n_args, args);
|
||||
|
||||
if (n_ready == 0) {
|
||||
return mp_const_empty_tuple;
|
||||
}
|
||||
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL));
|
||||
int ret_i = 0;
|
||||
struct pollfd *entries = self->entries;
|
||||
for (int i = 0; i < self->len; i++, entries++) {
|
||||
if (entries->revents != 0) {
|
||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
|
||||
// If there's an object stored, return it, otherwise raw fd
|
||||
if (self->obj_map && self->obj_map[i] != MP_OBJ_NULL) {
|
||||
t->items[0] = self->obj_map[i];
|
||||
} else {
|
||||
t->items[0] = MP_OBJ_NEW_SMALL_INT(entries->fd);
|
||||
}
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(entries->revents);
|
||||
ret_list->items[ret_i++] = MP_OBJ_FROM_PTR(t);
|
||||
if (self->flags & FLAG_ONESHOT) {
|
||||
entries->events = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(ret_list);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll);
|
||||
|
||||
STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
|
||||
if (self->ret_tuple == MP_OBJ_NULL) {
|
||||
self->ret_tuple = mp_obj_new_tuple(2, NULL);
|
||||
}
|
||||
|
||||
int n_ready = poll_poll_internal(n_args, args);
|
||||
self->iter_cnt = n_ready;
|
||||
self->iter_idx = 0;
|
||||
|
||||
return args[0];
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_ipoll_obj, 1, 3, poll_ipoll);
|
||||
|
||||
STATIC mp_obj_t poll_iternext(mp_obj_t self_in) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
if (self->iter_cnt == 0) {
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
}
|
||||
|
||||
self->iter_cnt--;
|
||||
|
||||
struct pollfd *entries = self->entries + self->iter_idx;
|
||||
for (int i = self->iter_idx; i < self->len; i++, entries++) {
|
||||
self->iter_idx++;
|
||||
if (entries->revents != 0) {
|
||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple);
|
||||
// If there's an object stored, return it, otherwise raw fd
|
||||
if (self->obj_map && self->obj_map[i] != MP_OBJ_NULL) {
|
||||
t->items[0] = self->obj_map[i];
|
||||
} else {
|
||||
t->items[0] = MP_OBJ_NEW_SMALL_INT(entries->fd);
|
||||
}
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(entries->revents);
|
||||
if (self->flags & FLAG_ONESHOT) {
|
||||
entries->events = 0;
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(t);
|
||||
}
|
||||
}
|
||||
|
||||
assert(!"inconsistent number of poll active entries");
|
||||
self->iter_cnt = 0;
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
STATIC mp_obj_t poll_dump(mp_obj_t self_in) {
|
||||
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
struct pollfd *entries = self->entries;
|
||||
for (int i = self->len - 1; i >= 0; i--) {
|
||||
printf("fd: %d ev: %x rev: %x", entries->fd, entries->events, entries->revents);
|
||||
if (self->obj_map) {
|
||||
printf(" obj: %p", self->obj_map[entries - self->entries]);
|
||||
}
|
||||
printf("\n");
|
||||
entries++;
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(poll_dump_obj, poll_dump);
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ipoll), MP_ROM_PTR(&poll_ipoll_obj) },
|
||||
#if DEBUG
|
||||
{ MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&poll_dump_obj) },
|
||||
#endif
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table);
|
||||
|
||||
STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
mp_type_poll,
|
||||
MP_QSTR_poll,
|
||||
MP_TYPE_FLAG_ITER_IS_ITERNEXT,
|
||||
iter, poll_iternext,
|
||||
locals_dict, &poll_locals_dict
|
||||
);
|
||||
|
||||
STATIC mp_obj_t select_poll(size_t n_args, const mp_obj_t *args) {
|
||||
int alloc = 4;
|
||||
if (n_args > 0) {
|
||||
alloc = mp_obj_get_int(args[0]);
|
||||
}
|
||||
mp_obj_poll_t *poll = mp_obj_malloc(mp_obj_poll_t, &mp_type_poll);
|
||||
poll->entries = m_new(struct pollfd, alloc);
|
||||
poll->alloc = alloc;
|
||||
poll->len = 0;
|
||||
poll->obj_map = NULL;
|
||||
poll->iter_cnt = 0;
|
||||
poll->ret_tuple = MP_OBJ_NULL;
|
||||
return MP_OBJ_FROM_PTR(poll);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_poll_obj, 0, 1, select_poll);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_select_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uselect) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mp_select_poll_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_POLLIN), MP_ROM_INT(POLLIN) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_POLLOUT), MP_ROM_INT(POLLOUT) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_POLLERR), MP_ROM_INT(POLLERR) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_POLLHUP), MP_ROM_INT(POLLHUP) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uselect = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_select_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_select, mp_module_uselect);
|
||||
|
||||
#endif // MICROPY_PY_USELECT_POSIX
|
@ -140,12 +140,6 @@ typedef long mp_off_t;
|
||||
#define MICROPY_STACKLESS_STRICT (0)
|
||||
#endif
|
||||
|
||||
// If settrace is enabled then we need code saving.
|
||||
#if MICROPY_PY_SYS_SETTRACE
|
||||
#define MICROPY_PERSISTENT_CODE_SAVE (1)
|
||||
#define MICROPY_COMP_CONST (0)
|
||||
#endif
|
||||
|
||||
// Unix-specific configuration of machine.mem*.
|
||||
#define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr
|
||||
#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr
|
||||
@ -162,13 +156,13 @@ typedef long mp_off_t;
|
||||
// Ensure builtinimport.c works with -m.
|
||||
#define MICROPY_MODULE_OVERRIDE_MAIN_IMPORT (1)
|
||||
|
||||
// Don't default sys.argv because we do that in main.
|
||||
// Don't default sys.argv and sys.path because we do that in main.
|
||||
#define MICROPY_PY_SYS_PATH_ARGV_DEFAULTS (0)
|
||||
|
||||
// Enable sys.executable.
|
||||
#define MICROPY_PY_SYS_EXECUTABLE (1)
|
||||
|
||||
#define MICROPY_PY_USOCKET_LISTEN_BACKLOG_DEFAULT (SOMAXCONN < 128 ? SOMAXCONN : 128)
|
||||
#define MICROPY_PY_SOCKET_LISTEN_BACKLOG_DEFAULT (SOMAXCONN < 128 ? SOMAXCONN : 128)
|
||||
|
||||
// Bare-metal ports don't have stderr. Printing debug to stderr may give tests
|
||||
// which check stdout a chance to pass, etc.
|
||||
@ -189,10 +183,10 @@ void mp_unix_mark_exec(void);
|
||||
#endif
|
||||
|
||||
// If enabled, configure how to seed random on init.
|
||||
#ifdef MICROPY_PY_URANDOM_SEED_INIT_FUNC
|
||||
#ifdef MICROPY_PY_RANDOM_SEED_INIT_FUNC
|
||||
#include <stddef.h>
|
||||
void mp_hal_get_random(size_t n, void *buf);
|
||||
static inline unsigned long mp_urandom_seed_init(void) {
|
||||
static inline unsigned long mp_random_seed_init(void) {
|
||||
unsigned long r;
|
||||
mp_hal_get_random(sizeof(r), &r);
|
||||
return r;
|
||||
|
@ -8,8 +8,8 @@ MICROPY_FORCE_32BIT = 0
|
||||
# 1 - use MicroPython version of readline
|
||||
MICROPY_USE_READLINE = 1
|
||||
|
||||
# btree module using Berkeley DB 1.xx
|
||||
# CIRCUITPY: not present
|
||||
# btree module using Berkeley DB 1.xx
|
||||
MICROPY_PY_BTREE = 0
|
||||
|
||||
# _thread module using pthreads
|
||||
@ -18,19 +18,22 @@ MICROPY_PY_THREAD = 1
|
||||
# Subset of CPython termios module
|
||||
MICROPY_PY_TERMIOS = 1
|
||||
|
||||
# CIRCUITPY: not present
|
||||
# Subset of CPython socket module
|
||||
MICROPY_PY_SOCKET = 0
|
||||
|
||||
# ffi module requires libffi (libffi-dev Debian package)
|
||||
MICROPY_PY_FFI = 1
|
||||
|
||||
# ussl module requires one of the TLS libraries below
|
||||
MICROPY_PY_USSL = 0
|
||||
# CIRCUITPY: not present
|
||||
# ssl module requires one of the TLS libraries below
|
||||
MICROPY_PY_SSL = 0
|
||||
# axTLS has minimal size but implements only a subset of modern TLS
|
||||
# functionality, so may have problems with some servers.
|
||||
MICROPY_SSL_AXTLS = 0
|
||||
# mbedTLS is more up to date and complete implementation, but also
|
||||
# more bloated.
|
||||
# CIRCUITPY: not present
|
||||
MICROPY_SSL_MBEDTLS = 0
|
||||
|
||||
# jni module requires JVM/JNI
|
||||
|
@ -191,6 +191,10 @@ void mp_thread_set_state(mp_state_thread_t *state) {
|
||||
pthread_setspecific(tls_key, state);
|
||||
}
|
||||
|
||||
mp_uint_t mp_thread_get_id(void) {
|
||||
return (mp_uint_t)pthread_self();
|
||||
}
|
||||
|
||||
void mp_thread_start(void) {
|
||||
// enable realtime priority if `-X realtime` command line parameter was set
|
||||
#if defined(__APPLE__)
|
||||
@ -210,7 +214,7 @@ void mp_thread_start(void) {
|
||||
mp_thread_unix_end_atomic_section();
|
||||
}
|
||||
|
||||
void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
||||
mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
||||
// default stack size is 8k machine-words
|
||||
if (*stack_size == 0) {
|
||||
*stack_size = 8192 * sizeof(void *);
|
||||
@ -265,7 +269,8 @@ void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
|
||||
|
||||
mp_thread_unix_end_atomic_section();
|
||||
|
||||
return;
|
||||
MP_STATIC_ASSERT(sizeof(mp_uint_t) >= sizeof(pthread_t));
|
||||
return (mp_uint_t)id;
|
||||
|
||||
er:
|
||||
mp_raise_OSError(ret);
|
||||
|
@ -192,8 +192,9 @@ main_term:;
|
||||
void mp_hal_stdout_tx_strn(const char *str, size_t len) {
|
||||
ssize_t ret;
|
||||
MP_HAL_RETRY_SYSCALL(ret, write(STDOUT_FILENO, str, len), {});
|
||||
// CIRCUITPY: need to conditionalize MICROPY_PY_OS_DUPTERM
|
||||
#if MICROPY_PY_OS_DUPTERM
|
||||
mp_uos_dupterm_tx_strn(str, len);
|
||||
mp_os_dupterm_tx_strn(str, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -262,7 +263,7 @@ void mp_hal_get_random(size_t n, void *buf) {
|
||||
#ifdef _HAVE_GETRANDOM
|
||||
RAISE_ERRNO(getrandom(buf, n, 0), errno);
|
||||
#else
|
||||
int fd = open("/dev/urandom", O_RDONLY);
|
||||
int fd = open("/dev/random", O_RDONLY);
|
||||
RAISE_ERRNO(fd, errno);
|
||||
RAISE_ERRNO(read(fd, buf, n), errno);
|
||||
close(fd);
|
||||
|
@ -33,13 +33,17 @@
|
||||
// Enable extra Unix features.
|
||||
#include "../mpconfigvariant_common.h"
|
||||
|
||||
// Enable testing of split heap.
|
||||
#define MICROPY_GC_SPLIT_HEAP (1)
|
||||
#define MICROPY_GC_SPLIT_HEAP_N_HEAPS (4)
|
||||
|
||||
// Enable additional features.
|
||||
#define MICROPY_DEBUG_PARSE_RULE_NAME (1)
|
||||
#define MICROPY_TRACKED_ALLOC (1)
|
||||
#define MICROPY_WARNINGS_CATEGORY (1)
|
||||
|
||||
// Disable things never used in circuitpython
|
||||
#define MICROPY_PY_UCRYPTOLIB (0)
|
||||
#define MICROPY_PY_UCRYPTOLIB_CTR (0)
|
||||
// CIRCUITPY Disable things never used in circuitpython
|
||||
#define MICROPY_PY_CRYPTOLIB (0)
|
||||
#define MICROPY_PY_CRYPTOLIB_CTR (0)
|
||||
#define MICROPY_PY_STRUCT (0) // uses shared-bindings struct
|
||||
#define MICROPY_GC_SPLIT_HEAP (0)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user