This commit is contained in:
Dmitry Borisenko
2021-12-22 14:06:24 +01:00
parent 1ed5c81eb7
commit 5e9b15e7de
483 changed files with 0 additions and 28088 deletions

View File

@@ -1,5 +0,0 @@
BasedOnStyle: Google
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
IncludeBlocks: Preserve

View File

@@ -1,4 +0,0 @@
github: bblanchon
custom:
- https://arduinojson.org/book/
- https://donate.benoitblanchon.fr/

View File

@@ -1,121 +0,0 @@
name: Continuous Integration
on: [push, pull_request]
jobs:
test:
name: Unit Test
runs-on: ubuntu-latest
steps:
- name: Install
run: sudo apt-get install -y lcov
- name: Checkout
uses: actions/checkout@v2
- name: Configure
run: cmake -DCOVERAGE=true .
- name: Build
run: cmake --build .
- name: Run tests
run: ctest --output-on-failure .
- name: Capture coverage data
run: lcov --capture --no-external --directory . --output-file coverage.info
- name: Filter coverage data
run: lcov --remove coverage.info "$(pwd)/extras/*" --output-file coverage_filtered.info
- name: Generate coverage report
run: mkdir coverage && genhtml coverage_filtered.info -o coverage -t ArduinoJson
- name: Upload coverage report
uses: actions/upload-artifact@v2
with:
name: coverage
path: coverage
- name: Upload to Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: coverage_filtered.info
platformio:
name: PlatformIO
needs: test
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- platform: atmelavr
board: leonardo
eeprom: true
softwareserial: true
- platform: espressif8266
board: huzzah
eeprom: true
softwareserial: true
- platform: espressif32
board: esp32dev
eeprom: true
softwareserial: false
- platform: atmelsam
board: mkr1000USB
eeprom: false
softwareserial: false
- platform: teensy
board: teensy31
eeprom: true
softwareserial: true
- platform: ststm32
board: nucleo_f031k6
eeprom: true
softwareserial: true
- platform: nordicnrf52
board: adafruit_feather_nrf52840
eeprom: false
softwareserial: true
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up cache
uses: actions/cache@v2
with:
path: |
~/.platformio
~/.cache/pip
key: ${{ runner.os }}-platformio
- name: Set up Python 3.x
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install PlatformIO
run: pip install platformio
- name: Install platform "${{ matrix.platform }}"
run: platformio platform install ${{ matrix.platform }}
- name: Install adafruit-nrfutil
if: ${{ matrix.platform == 'nordicnrf52' }}
run: pip3 install adafruit-nrfutil
- name: Include Adafruit_TinyUSB.h # https://github.com/adafruit/Adafruit_nRF52_Arduino/issues/653
if: ${{ matrix.platform == 'nordicnrf52' }}
run: find examples/ -name '*.ino' -exec sed -i 's/\(#include <StreamUtils.h>\)/\1\n#include <Adafruit_TinyUSB.h>/' {} +
- name: Build EepromRead
if: ${{ matrix.eeprom }}
run: platformio ci "examples/EepromRead/EepromRead.ino" -l '.' -b ${{ matrix.board }}
- name: Build EepromWrite
if: ${{ matrix.eeprom }}
run: platformio ci "examples/EepromWrite/EepromWrite.ino" -l '.' -b ${{ matrix.board }}
- name: Build HammingSerial1
run: platformio ci "examples/HammingSerial1/HammingSerial1.ino" -l '.' -b ${{ matrix.board }}
- name: Build HammingSoftwareSerial
if: ${{ matrix.softwareserial }}
run: platformio ci "examples/HammingSoftwareSerial/HammingSoftwareSerial.ino" -l '.' -b ${{ matrix.board }}
- name: Build Logger
run: platformio ci "examples/Logger/Logger.ino" -l '.' -b ${{ matrix.board }}
- name: Build ReadBuffer
run: platformio ci "examples/ReadBuffer/ReadBuffer.ino" -l '.' -b ${{ matrix.board }}
- name: Build ReadLogger
run: platformio ci "examples/ReadLogger/ReadLogger.ino" -l '.' -b ${{ matrix.board }}
- name: Build StringPrint
run: platformio ci "examples/StringPrint/StringPrint.ino" -l '.' -b ${{ matrix.board }}
- name: Build StringStream
run: platformio ci "examples/StringStream/StringStream.ino" -l '.' -b ${{ matrix.board }}
- name: Build WriteBuffer
run: platformio ci "examples/WriteBuffer/WriteBuffer.ino" -l '.' -b ${{ matrix.board }}
- name: Build WriteLogger
run: platformio ci "examples/WriteLogger/WriteLogger.ino" -l '.' -b ${{ matrix.board }}

View File

@@ -1,2 +0,0 @@
/build

View File

@@ -1,79 +0,0 @@
StreamUtils - Change log
========================
HEAD
----
* Support `Print::flush()` on AVR
1.6.1 (2021/94/05)
-----
* Add example `HammingSerial1.ino`
* Add support for STM32 (issue #11)
1.6.0 (2020/11/20)
-----
* Add `HammingPrint<7, 4>`
* Add `HammingStream<7, 4>`, `HammingEncodingStream<7, 4>`, and `HammingDecodingStream<7, 4>`
* Add `HammingClient<7, 4>`, `HammingEncodingClient<7, 4>`, and `HammingDecodingClient<7, 4>`
1.5.0 (2020/08/04)
-----
* Add `WaitingPrint`, `WriteWaitingClient`, and `WriteWaitingStream`.
1.4.1 (2020/07/01)
-----
* Fix unwanted waits in `ReadBufferingClient` and `ReadBufferingStream`.
* Stop calling `Client::read()` in place of `Stream::readBytes()`,
because it doesn't honor the timeout.
1.4.0 (2020/03/30)
-----
* Add `EepromStream`
* Add support for ESP32
* Add support for Teensy
1.3.0 (2020/01/20)
-----
* Move auxiliary content to `extras/` to comply with new library layout
* Add `StringPrint` and `StringStream`
* Extract `StreamUtils.hpp`, same as `StreamUtils.h` except it keeps everything in the `StreamUtils` namespace.
1.2.2 (2019/07/18)
-----
* Fix `BufferingPrint` taking `Stream` instead of `Print` (issue #3)
* Fix `LoggingPrint` not forwarding call to `Print::flush()`
* Fix missing `override` specifiers
1.2.1 (2019/06/05)
-----
* Remove workaround for ESP8266 core 2.5.0
* Fix compatibility with ESP8266 core 2.5.1+ (issue #2)
1.2.0 (2019/05/01)
-----
* Add `LoggingPrint`
* Add `BufferingPrint`
* Add `WriteLoggingClient`, `ReadLoggingClient`, and `LoggingClient`
* Add `WriteBufferingClient` and `ReadBufferingClient`
1.1.0 (2019/04/20)
-----
* Add `LoggingStream` (=`ReadLoggingStream` + `WriteLoggingStream`)
1.0.0 (2019/04/14)
-----
* Add `ReadBufferingStream` and `WriteBufferingStream`
* Add `ReadLoggingStream` and `WriteLoggingStream`

View File

@@ -1,18 +0,0 @@
# StreamUtils - github.com/bblanchon/ArduinoStreamUtils
# Copyright Benoit Blanchon 2019-2021
# MIT License
cmake_minimum_required(VERSION 3.0)
project(StreamUtils)
enable_testing()
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(${COVERAGE})
set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage -g -O0")
endif()
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
add_subdirectory(extras/test)

View File

@@ -1,10 +0,0 @@
The MIT License (MIT)
---------------------
Copyright © 2019 Benoit BLANCHON
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.

View File

@@ -1,369 +0,0 @@
StreamUtils: Power-ups for Arduino Streams
==========================================
[![arduino-library-badge](https://www.ardu-badge.com/badge/StreamUtils.svg?version=1.6.1)](https://www.ardu-badge.com/StreamUtils/1.6.1)
[![Continuous Integration](https://github.com/bblanchon/ArduinoStreamUtils/workflows/Continuous%20Integration/badge.svg)](https://github.com/bblanchon/ArduinoStreamUtils/actions/workflows/ci.yml)
[![Coverage Status](https://coveralls.io/repos/github/bblanchon/ArduinoStreamUtils/badge.svg)](https://coveralls.io/github/bblanchon/ArduinoStreamUtils)
The *stream* is an essential abstraction in Arduino; we find it in many places:
* [`HardwareSerial`](https://www.arduino.cc/reference/en/language/functions/communication/serial/)
* [`SoftwareSerial`](https://www.arduino.cc/en/Reference/SoftwareSerial)
* [`File`](https://www.arduino.cc/en/Reference/SD)
* [`EthernetClient`](https://www.arduino.cc/en/Reference/EthernetClient)
* [`WiFiClient`](https://www.arduino.cc/en/Reference/WiFiClient)
* [`Wire`](https://www.arduino.cc/en/reference/wire)
* and many others...
This library provides some helper classes and functions for dealing with streams.
For example, with this library, you can:
* speed of your program by buffering the data it reads from a file
* reduce the number of packets sent over WiFi by buffering the data you send
* improve the reliability of a serial connection by adding error correction codes
* debug your program more easily by logging what it sends to a Web service
* send large data with the [Wire library](https://www.arduino.cc/en/reference/wire)
* use a `String` or EEPROM with a stream interface
Read on to see how StreamUtils can help you!
How to add buffering to a Stream?
---------------------------------
### Buffering read operations
Sometimes, you can significantly improve performance by reading many bytes at once.
For example, [according to SPIFFS's wiki](https://github.com/pellepl/spiffs/wiki/Performance-and-Optimizing#reading-files), it's much faster to read files in chunks of 64 bytes than reading them one byte at a time.
![ReadBufferingStream](extras/images/ReadBuffer.svg)
To buffer the input, simply decorate the original `Stream` with `ReadBufferingStream`. For example, suppose your program reads a JSON document from SPIFFS, like that:
```c++
File file = SPIFFS.open("example.json", "r");
deserializeJson(doc, file);
```
Then you simply need to insert one line to greatly improve the reading speed:
```c++
File file = SPIFFS.open("example.json", "r");
ReadBufferingStream bufferedFile{file, 64}; // <- HERE
deserializeJson(doc, bufferedFile);
```
Unfortunately, this optimization is only possible if:
1. `Stream.readBytes()` is declared `virtual` in your Arduino Code (as it's the case for ESP8266), and
2. the derived class has an optimized implementation of `readBytes()` (as it's the case for SPIFFS' `File`).
When possible, prefer `ReadBufferingClient` to `ReadBufferingStream` because `Client` defines a `read()` method similar to `readBytes()`, except that this one is `virtual` on all platforms.
If memory allocation fails, `ReadBufferingStream` behaves as if no buffer was used: it forwards all calls to the upstream `Stream`.
Adding a buffer only makes sense for **unbuffered** streams. For example, there is **no benefit to adding a buffer to serial ports** because they already include an internal buffer.
### Buffering write operations
Similarly, you can improve performance significantly by writing many bytes at once.
For example, if you write to `WiFiClient` one bytes at a time, it will be very slow; it's much faster if you send large chunks.
![WriteBufferingStream](extras/images/WriteBuffer.svg)
To add a buffer, decorate the original `Stream` with `WriteBufferingStream`. For example, if your program sends a JSON document via `WiFiClient`, like that:
```c++
serializeJson(doc, wifiClient);
```
Then, you just need to add two lines:
```c++
WriteBufferingStream bufferedWifiClient{wifiClient, 64};
serializeJson(doc, bufferedWifiClient);
bufferedWifiClient.flush();
```
`flush()` sends the remaining data; if you forget to call it, the end of the message will be missing. The destructor of `WriteBufferingStream` calls `flush()`, so you can remove this line if you destroy the decorator immediately.
If memory allocation fails, `WriteBufferingStream` behaves as if no buffer was used: it forwards all calls to the upstream `Stream`.
Adding a buffer only makes sense for **unbuffered** streams. For example, there is **no benefit to adding a buffer to serial ports** because they already include an internal buffer.
How to add logging to a stream?
-------------------------------
### Logging write operations
When debugging a program that makes HTTP requests, the first thing you want to check is that the request is correct. With this library, you can decorate the `EthernetClient` or the `WiFiClient` to log everything to the serial.
![WriteLoggingStream](extras/images/WriteLogger.svg)
For example, if you program is:
```c++
client.println("GET / HTTP/1.1");
client.println("User-Agent: Arduino");
// ...
```
Then, you just need to create the decorator, and update the calls to `println()`:
```c++
WriteLoggingStream loggingClient(client, Serial);
loggingClient.println("GET / HTTP/1.1");
loggingClient.println("User-Agent: Arduino");
// ...
```
Everything you write to `loggingClient` is written to `client` and logged to `Serial`.
### Logging read operations
Similarly, you often want to see what the HTTP server sent back. With this library, you can decorate the `EthernetClient` or the `WiFiClient` to log everything to the serial.
![ReadLoggingStream](extras/images/ReadLogger.svg)
For example, if you program is:
```c++
char response[256];
client.readBytes(response, 256);
```
Then, you just need to create the decorator, and update the calls to `readBytes()`:
```c++
ReadLoggingStream loggingClient(client, Serial);
char response[256];
loggingClient.readBytes(response, 256);
// ...
```
`loggingClient` forwards all operations to `client` and logs read operation to `Serial`.
⚠ **WARNING** ⚠
If your program receives data from one serial port and logs to another one, **make sure the latter runs at a much higher speed**. Logging must be at least ten times faster, or it will slow down the receiving port, which may drop incoming bytes.
### Logging read and write operations
Of course, you could log read and write operations by combining `ReadLoggingStream` and `WriteLoggingStream`, but there is a simpler solution: `LoggingStream`.
![LoggingStream](extras/images/Logger.svg)
As usual, if your program is:
```c++
client.println("GET / HTTP/1.1");
client.println("User-Agent: Arduino");
char response[256];
client.readBytes(response, 256);
```
Then decorate `client` and replace the calls:
```c++
LoggingStream loggingClient(client, Serial);
loggingClient.println("GET / HTTP/1.1");
loggingClient.println("User-Agent: Arduino");
char response[256];
loggingClient.readBytes(response, 256);
```
How to use error-correction codes (ECC)?
----------------------------------------
StreamUtils supports the [Hamming(7, 4)](https://en.wikipedia.org/wiki/Hamming(7,4)) error-correction code, which encodes 4 bits of data into 7 bits by adding three parity bits.
These extra bits increase the amount of traffic but allow correcting any one-bit error within the 7 bits.
If you use this encoding on an 8-bit channel, it effectively doubles the amount of traffic. However, if you use an [`HardwareSerial`](https://www.arduino.cc/reference/en/language/functions/communication/serial/) instance (like `Serial`, `Serial1`...), you can slightly reduce the overhead by configuring the ports as a 7-bit channel, like so:
```c++
// Initialize serial port with 9600 bauds, 7-bits of data, no parity, and one stop bit
Serial1.begin(9600, SERIAL_7N1);
```
### Adding parity bits
The class `HammingEncodingStream<7, 4>` decorates an existing `Stream` to include parity bits in every write operation.
![HammingEncodingStream](extras/images/HammingEncodingStream.svg)
You can use this class like so:
```c++
HammingEncodingStream<7, 4> eccSerial(Serial1);
eccSerial.println("Hello world!");
```
Like every `Stream` decorator in this library, `HammingEncodingStream<7, 4>` supports all `Stream` methods (like `print()`, `println()`, `read()`, `readBytes()`, and `available()`).
### Correcting errors
The class `HammingDecodingStream<7, 4>` decorates an existing `Stream` to decode parity bits in every read operation.
![HammingDecodingStream](extras/images/HammingDecodingStream.svg)
You can use this class like so:
```c++
HammingDecodingStream<7, 4> eccSerial(Serial1);
char buffer[256];
size_t n = eccSerial.readBytes(buffer, n);
```
Like every `Stream` decorator in this library, `HammingDecodingStream<7, 4>` supports all `Stream` methods (like `print()`, `println()`, `read()`, `readBytes()`, and `available()`).
### Encoding and decoding in both directions
The class `HammingStream<7, 4>` combines the features of `HammingEncodingStream<7, 4>` and `HammingDecodingStream<7, 4>`, which is very useful when you do a two-way communication.
![HammingStream](extras/images/HammingStream.svg)
You can use this class like so:
```c++
HammingStream<7, 4> eccSerial(Serial1);
eccSerial.println("Hello world!");
char buffer[256];
size_t n = eccSerial.readBytes(buffer, n);
```
Like every `Stream` decorator in this library, `HammingStream<7, 4>` supports all `Stream` methods (like `print()`, `println()`, `read()`, `readBytes()`, and `available()`).
How to retry write operations?
------------------------------
Sometimes, a stream is limited to the capacity of its internal buffer. In that case, you must wait before sending more data.
To solve this problem, StreamUtils provides the `WriteWaitingStream` decorator:
![WriteWaitingStream](extras/images/WriteWaitingStream.svg)
This function repeatedly waits and retries until it times out.
You can customize the `wait()` function; by default, it's [`yield()`](https://www.arduino.cc/en/Reference/SchedulerYield).
For example, if you want to send more than 32 bytes with the [Wire library](https://www.arduino.cc/en/reference/wire), you can do:
```c++
WriteWaitingStream wireStream(Wire, [](){
Wire.endTransmission(false); // <- don't forget this argument
Wire.beginTransmission(address);
});
Wire.beginTransmission(address);
wireStream.print("This is a very very long message that I'm sending!");
Wire.endTransmission();
```
As you can see, we use the `wait()` function as a hook to flush the Wire transmission buffer. Notice that we pass `false` to [`endTransmission()`](https://www.arduino.cc/en/Reference/WireEndTransmission) so that it sends the data but doesn't actually stop the transmission.
How to use a `String` as a stream?
---------------------
### Writing to a `String`
Sometimes, you use a piece of code that expects a `Print` instance (like `ReadLoggingStream`), but you want the output in a `String` instead of a regular `Stream`.
In that case, use the `StringPrint` class. It wraps a `String` within a `Print` implementation.
![StringPrint](extras/images/StringPrint.svg)
Here is how you can use it:
```c++
StringPrint stream;
stream.print("Temperature = ");
stream.print(22.3);
stream.print(" °C");
String result = stream.str();
```
At the end of this snippet, the string `result` contains:
```
Temperature = 22.30 °C
```
### Reading from a `String`
Similarly, there are cases where you have a `String`, but you need to pass a `Stream` to some other piece of code. In that case, use `StringStream`; it's similar to `StrintPrint`, except you can read as well.
![StringStream](extras/images/StringStream.svg)
How to use EEPROM as a stream?
------------------------------
SteamUtils also allows using EEPROM as a stream. Simply create an instance of `EepromStream` and specify the start address and the size of the region you want to expose.
![EepromStream](extras/images/EepromStream.svg)
For example, it allows you to save a JSON document in EEPROM:
```c++
EepromStream eepromStream(0, 128);
serializeJson(doc, eepromStream);
eepromStream.flush(); // <- calls EEPROM.commit() on ESP (optional)
```
In the same way, you can read a JSON document from EEPROM:
```c++
EepromStream eepromStream(0, 128);
deserializeJson(doc, eepromStream);
```
Summary
-------
Some of the decorators are also available for the `Print` and `Client` classes.
See the equivalence table below.
| Purpose | `Client` | `Stream` | `Print` |
|:-----------------------------------|:------------------------|:------------------------|:-----------------|
| Log *write* operations | `WriteLoggingClient` | `WriteLoggingStream` | `LoggingPrint` |
| Log *read* operations | `ReadLoggingClient` | `ReadLoggingStream` | |
| Log *read* and *write* op. | `LoggingClient` | `LoggingStream` | |
| Buffer *write* operations | `WriteBufferingClient` | `WriteBufferingStream` | `BufferingPrint` |
| Buffer *read* operations | `ReadBufferingClient` | `ReadBufferingStream` | |
| Repeat *write* operations | `WriteWaitingClient` | `WriteWaitingStream` | `WaitingPrint` |
| Use `String` as a stream | | `StringStream` | `StringPrint` |
| Use EEPROM as a stream | | `EepromStream` | |
| Error correction (decode only) | `HammingDecodingClient` | `HammingDecodingStream` | |
| Error correction (encode only) | `HammingEncodingClient` | `HammingEncodingStream` | `HammingPrint` |
| Error correction (encode & decode) | `HammingClient` | `HammingStream` | |
When possible, prefer `ReadBufferingClient` to `ReadBufferingStream` because `Client::read()` often provides an optimized implementation.
Portability
-----------
This library relies on the definitions of `Client`, `Print`, and `Stream`, which unfortunately differ from one core to another.
It has been tested on the following cores:
* [AVR](https://github.com/arduino/ArduinoCore-avr)
* [ESP32](https://github.com/espressif/arduino-esp32)
* [ESP8266](https://github.com/esp8266/Arduino)
* [nRF52](https://github.com/adafruit/Adafruit_nRF52_Arduino)
* [SAMD](https://github.com/arduino/ArduinoCore-samd)
* [STM32](https://github.com/stm32duino/Arduino_Core_STM32)
* [Teensy](https://github.com/PaulStoffregen/cores)
If your core is not supported, please [open an issue](https://github.com/bblanchon/ArduinoStreamUtils/issues/new).
Thank you for your understanding.

View File

@@ -1,63 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
//
// This example shows how to read from EEPROM
#include <StreamUtils.h>
void setup() {
// Initialize serial port
Serial.begin(9600);
while (!Serial)
continue;
#if STREAMUTILS_ENABLE_EEPROM
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
Serial.println("Initializing EEPROM...");
EEPROM.begin(512);
#endif
Serial.println("Make sure to run the EepromWrite example first!");
Serial.println("Reading EEPROM... ");
EepromStream s(0, 12);
Serial.print(s.readString());
#else
Serial.println("EepromStream is not supported on this platform. Sorry");
#endif
}
void loop() {
// not used in this example
}
/*****************************************************
* *
* Love this project? *
* Star it on GitHub! *
* *
* .,,. *
* ,,:1. *
* ,.,:;1 *
* .,,,::;: *
* ,,,,::;;. *
* .,,,:::;;; *
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
* .;;;:::,,,,,,,,::::::;:::;;1t: *
* :;;:,,,,,,::::::;;;;;;l1 *
* ,,,,:::::::;;;;;;l *
* .,,,,::::;;;;;;;:::: *
* ,,,,,:::;;;;;::,:::1 *
* ,,,,,::;;;t1:,,:::::;l *
* .,,,,:;;ll ;::::::;;, *
* ,,,:;ll. .1:::;;l *
* .,:lt, .1;;l: *
* *
* https://github.com/bblanchon/ArduinoStreamUtils *
* *
*****************************************************/

View File

@@ -1,69 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
//
// This example shows how to read from EEPROM
#include <StreamUtils.h>
void setup() {
// Initialize serial port
Serial.begin(9600);
while (!Serial)
continue;
#if STREAMUTILS_ENABLE_EEPROM
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
Serial.println("Initializing EEPROM...");
EEPROM.begin(512);
#endif
Serial.println("Writing to EEPROM...");
EepromStream s(0, 12);
s.print("Hello World!");
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
Serial.println("Saving...");
s.flush(); // only required on ESP
#endif
Serial.println("Done!");
Serial.println("Now, run the EepromRead example.");
#else
Serial.println("EepromStream is not supported on this platform. Sorry");
#endif
}
void loop() {
// not used in this example
}
/*****************************************************
* *
* Love this project? *
* Star it on GitHub! *
* *
* .,,. *
* ,,:1. *
* ,.,:;1 *
* .,,,::;: *
* ,,,,::;;. *
* .,,,:::;;; *
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
* .;;;:::,,,,,,,,::::::;:::;;1t: *
* :;;:,,,,,,::::::;;;;;;l1 *
* ,,,,:::::::;;;;;;l *
* .,,,,::::;;;;;;;:::: *
* ,,,,,:::;;;;;::,:::1 *
* ,,,,,::;;;t1:,,:::::;l *
* .,,,,:;;ll ;::::::;;, *
* ,,,:;ll. .1:::;;l *
* .,:lt, .1;;l: *
* *
* https://github.com/bblanchon/ArduinoStreamUtils *
* *
*****************************************************/

View File

@@ -1,68 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
//
// This example shows how to use Hamming codes for error correction
//
// To run this program, you need two boards that support Serial1 with the same
// voltage. For example: Arduino Mega, Leonardo, or Nano Every (all 5V boards)
//
// Connect the TX pin of one board to the RX pin of the other and vice-versa.
#include <StreamUtils.h>
HammingStream<7, 4> eccSerial1(Serial1);
void setup() {
Serial.begin(115200);
while (!Serial)
continue;
Serial1.begin(9600);
while (!Serial)
continue;
// Discard any remaining data in the input buffer
while (Serial1.available())
Serial1.read();
}
void loop() {
// Did we receive something?
if (eccSerial1.available())
// Print it
Serial.write(eccSerial1.read());
// Do we have something to send?
if (Serial.available())
// Sent it
eccSerial1.write(Serial.read());
}
/*****************************************************
* *
* Love this project? *
* Star it on GitHub! *
* *
* .,,. *
* ,,:1. *
* ,.,:;1 *
* .,,,::;: *
* ,,,,::;;. *
* .,,,:::;;; *
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
* .;;;:::,,,,,,,,::::::;:::;;1t: *
* :;;:,,,,,,::::::;;;;;;l1 *
* ,,,,:::::::;;;;;;l *
* .,,,,::::;;;;;;;:::: *
* ,,,,,:::;;;;;::,:::1 *
* ,,,,,::;;;t1:,,:::::;l *
* .,,,,:;;ll ;::::::;;, *
* ,,,:;ll. .1:::;;l *
* .,:lt, .1;;l: *
* *
* https://github.com/bblanchon/ArduinoStreamUtils *
* *
*****************************************************/

View File

@@ -1,67 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
//
// This example shows how to use Hamming codes for error correction
//
// To run this program, you need two boards connected like so:
// BOARD 1 - BOARD 2
// pin 10 - pin 11
// pin 11 - pin 10
//
// SoftwareSerial is here for demonstration purposes; please don't use it in
// production, as it is notoriously unreliable.
#include <SoftwareSerial.h>
#include <StreamUtils.h>
SoftwareSerial linkSerial(10, 11); // RX, TX
HammingStream<7, 4> eccLinkSerial(linkSerial);
void setup() {
Serial.begin(115200);
while (!Serial)
continue;
linkSerial.begin(4800);
}
void loop() {
// Did we receive something?
if (eccLinkSerial.available())
// Print it
Serial.write(eccLinkSerial.read());
// Do we have something to send?
if (Serial.available())
// Sent it
eccLinkSerial.write(Serial.read());
}
/*****************************************************
* *
* Love this project? *
* Star it on GitHub! *
* *
* .,,. *
* ,,:1. *
* ,.,:;1 *
* .,,,::;: *
* ,,,,::;;. *
* .,,,:::;;; *
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
* .;;;:::,,,,,,,,::::::;:::;;1t: *
* :;;:,,,,,,::::::;;;;;;l1 *
* ,,,,:::::::;;;;;;l *
* .,,,,::::;;;;;;;:::: *
* ,,,,,:::;;;;;::,:::1 *
* ,,,,,::;;;t1:,,:::::;l *
* .,,,,:;;ll ;::::::;;, *
* ,,,:;ll. .1:::;;l *
* .,:lt, .1;;l: *
* *
* https://github.com/bblanchon/ArduinoStreamUtils *
* *
*****************************************************/

View File

@@ -1,61 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
//
// This example shows how to log what goes through a Stream, both reads and
// writes operations.
#include <StreamUtils.h>
// Create a new stream that will forward all calls to Serial, and log to Serial.
// Everything will be written twice to the Serial!
LoggingStream loggingStream(Serial, Serial);
void setup() {
// Initialize serial port
Serial.begin(9600);
while (!Serial)
continue;
// Write to the serial port.
// Because loggingStream logs each write operation, the string will we written
// twice
loggingStream.println("Hello World!");
}
void loop() {
// Read from the serial port.
// Because loggingStream logs each read operation, everything we read is
// printed back to the serial port.
while (loggingStream.available()) {
loggingStream.read();
}
}
/*****************************************************
* *
* Love this project? *
* Star it on GitHub! *
* *
* .,,. *
* ,,:1. *
* ,.,:;1 *
* .,,,::;: *
* ,,,,::;;. *
* .,,,:::;;; *
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
* .;;;:::,,,,,,,,::::::;:::;;1t: *
* :;;:,,,,,,::::::;;;;;;l1 *
* ,,,,:::::::;;;;;;l *
* .,,,,::::;;;;;;;:::: *
* ,,,,,:::;;;;;::,:::1 *
* ,,,,,::;;;t1:,,:::::;l *
* .,,,,:;;ll ;::::::;;, *
* ,,,:;ll. .1:::;;l *
* .,:lt, .1;;l: *
* *
* https://github.com/bblanchon/ArduinoStreamUtils *
* *
*****************************************************/

View File

@@ -1,56 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
//
// This example shows how to buffer the read operations of a stream.
//
// Like "echo," it reads from the serial port and prints back the same thing.
// What's interesting with this program is that it reads the input in chunks of
// 64 bytes, even if it seems to read them one by one.
#include <StreamUtils.h>
ReadBufferingStream bufferedSerial{Serial, 64};
void setup() {
// Initialize serial port
Serial.begin(9600);
while (!Serial)
continue;
}
void loop() {
// Even if it looks like the bytes are extracted one by one, they are actually
// read by chunks of 64 bytes and placed in a buffer.
while (bufferedSerial.available()) {
Serial.write(bufferedSerial.read());
}
}
/*****************************************************
* *
* Love this project? *
* Star it on GitHub! *
* *
* .,,. *
* ,,:1. *
* ,.,:;1 *
* .,,,::;: *
* ,,,,::;;. *
* .,,,:::;;; *
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
* .;;;:::,,,,,,,,::::::;:::;;1t: *
* :;;:,,,,,,::::::;;;;;;l1 *
* ,,,,:::::::;;;;;;l *
* .,,,,::::;;;;;;;:::: *
* ,,,,,:::;;;;;::,:::1 *
* ,,,,,::;;;t1:,,:::::;l *
* .,,,,:;;ll ;::::::;;, *
* ,,,:;ll. .1:::;;l *
* .,:lt, .1;;l: *
* *
* https://github.com/bblanchon/ArduinoStreamUtils *
* *
*****************************************************/

View File

@@ -1,55 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
//
// This example shows how to log what read from a Stream
#include <StreamUtils.h>
// Create a new stream that will forward all calls to Serial, and log to Serial.
// It will write back everything it reads, just like "echo"
ReadLoggingStream loggingStream(Serial, Serial);
void setup() {
// Initialize serial port
Serial.begin(9600);
while (!Serial)
continue;
}
void loop() {
// Read the serial port.
// Because loggingStream write everything it read, the program will show what
// you sent.
while (Serial.available()) {
loggingStream.write(Serial.read());
}
}
/*****************************************************
* *
* Love this project? *
* Star it on GitHub! *
* *
* .,,. *
* ,,:1. *
* ,.,:;1 *
* .,,,::;: *
* ,,,,::;;. *
* .,,,:::;;; *
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
* .;;;:::,,,,,,,,::::::;:::;;1t: *
* :;;:,,,,,,::::::;;;;;;l1 *
* ,,,,:::::::;;;;;;l *
* .,,,,::::;;;;;;;:::: *
* ,,,,,:::;;;;;::,:::1 *
* ,,,,,::;;;t1:,,:::::;l *
* .,,,,:;;ll ;::::::;;, *
* ,,,:;ll. .1:::;;l *
* .,:lt, .1;;l: *
* *
* https://github.com/bblanchon/ArduinoStreamUtils *
* *
*****************************************************/

View File

@@ -1,54 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
//
// This example shows how to use StringPrint
#include <StreamUtils.h>
void setup() {
// Initialize serial port
Serial.begin(9600);
while (!Serial)
continue;
StringPrint stream;
stream.print("Temperature = ");
stream.print(22.3);
stream.print(" °C");
Serial.print(stream.str());
}
void loop() {
// no used in this example
}
/*****************************************************
* *
* Love this project? *
* Star it on GitHub! *
* *
* .,,. *
* ,,:1. *
* ,.,:;1 *
* .,,,::;: *
* ,,,,::;;. *
* .,,,:::;;; *
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
* .;;;:::,,,,,,,,::::::;:::;;1t: *
* :;;:,,,,,,::::::;;;;;;l1 *
* ,,,,:::::::;;;;;;l *
* .,,,,::::;;;;;;;:::: *
* ,,,,,:::;;;;;::,:::1 *
* ,,,,,::;;;t1:,,:::::;l *
* .,,,,:;;ll ;::::::;;, *
* ,,,:;ll. .1:::;;l *
* .,:lt, .1;;l: *
* *
* https://github.com/bblanchon/ArduinoStreamUtils *
* *
*****************************************************/

View File

@@ -1,55 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
//
// This example shows how to use StringStream
#include <StreamUtils.h>
StringStream stream;
void setup() {
// Initialize serial port
Serial.begin(9600);
while (!Serial)
continue;
stream.print("Temperature = ");
stream.print(22.3);
stream.print(" °C");
}
void loop() {
if (stream.available() > 0) {
Serial.print((char)stream.read());
}
delay(250);
}
/*****************************************************
* *
* Love this project? *
* Star it on GitHub! *
* *
* .,,. *
* ,,:1. *
* ,.,:;1 *
* .,,,::;: *
* ,,,,::;;. *
* .,,,:::;;; *
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
* .;;;:::,,,,,,,,::::::;:::;;1t: *
* :;;:,,,,,,::::::;;;;;;l1 *
* ,,,,:::::::;;;;;;l *
* .,,,,::::;;;;;;;:::: *
* ,,,,,:::;;;;;::,:::1 *
* ,,,,,::;;;t1:,,:::::;l *
* .,,,,:;;ll ;::::::;;, *
* ,,,:;ll. .1:::;;l *
* .,:lt, .1;;l: *
* *
* https://github.com/bblanchon/ArduinoStreamUtils *
* *
*****************************************************/

View File

@@ -1,62 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
//
// This example shows how to buffer writes to a stream.
//
// Like "echo," it reads from the serial port and prints back the same thing.
// What's interesting with this program is that it writes in chunks of
// 8 bytes, even if it seems to write them one by one.
//
// As you'll see, you need to type at least 8 bytes to see something. That's
// because it waits for the buffered to be full before sending it to the serial.
#include <StreamUtils.h>
// Create a new Stream that buffers all writes to Serial
WriteBufferingStream bufferedSerial{Serial, 8};
void setup() {
// Initialize serial port
Serial.begin(9600);
while (!Serial)
continue;
Serial.println(F("Send at least 8 bytes to see the result"));
}
void loop() {
// Even if it looks like the bytes are sent one by one, they are actual
// written in chunks of 8 bytes.
while (Serial.available()) {
bufferedSerial.write(Serial.read());
}
}
/*****************************************************
* *
* Love this project? *
* Star it on GitHub! *
* *
* .,,. *
* ,,:1. *
* ,.,:;1 *
* .,,,::;: *
* ,,,,::;;. *
* .,,,:::;;; *
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
* .;;;:::,,,,,,,,::::::;:::;;1t: *
* :;;:,,,,,,::::::;;;;;;l1 *
* ,,,,:::::::;;;;;;l *
* .,,,,::::;;;;;;;:::: *
* ,,,,,:::;;;;;::,:::1 *
* ,,,,,::;;;t1:,,:::::;l *
* .,,,,:;;ll ;::::::;;, *
* ,,,:;ll. .1:::;;l *
* .,:lt, .1;;l: *
* *
* https://github.com/bblanchon/ArduinoStreamUtils *
* *
*****************************************************/

View File

@@ -1,55 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
//
// This example shows how to log what written to a Stream
#include <StreamUtils.h>
// Create a new stream that will forward all calls to Serial, and log to Serial.
// Everything will be written twice to the Serial!
WriteLoggingStream loggingStream(Serial, Serial);
void setup() {
// Initialize serial port
Serial.begin(9600);
while (!Serial)
continue;
// Write to the serial port.
// Because loggingStream logs each write operation, the string will we written
// twice
loggingStream.println("Hello World!");
}
void loop() {
// not used in this example
}
/*****************************************************
* *
* Love this project? *
* Star it on GitHub! *
* *
* .,,. *
* ,,:1. *
* ,.,:;1 *
* .,,,::;: *
* ,,,,::;;. *
* .,,,:::;;; *
* .....,,,,...,.,,,,,,:::,,,,,,,,,,,,, *
* ,,,,,,,,,,,:,...,,,,,,:::,,,,:::;;;11l *
* .;::::::::,,,,,,,,,,:::::,,::;;;1lt *
* .;;;:::,,,,,,,,::::::;:::;;1t: *
* :;;:,,,,,,::::::;;;;;;l1 *
* ,,,,:::::::;;;;;;l *
* .,,,,::::;;;;;;;:::: *
* ,,,,,:::;;;;;::,:::1 *
* ,,,,,::;;;t1:,,:::::;l *
* .,,,,:;;ll ;::::::;;, *
* ,,,:;ll. .1:::;;l *
* .,:lt, .1;;l: *
* *
* https://github.com/bblanchon/ArduinoStreamUtils *
* *
*****************************************************/

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker id="a" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker id="b" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><rect ry="1.228" rx="1.228" y=".25" x="38.123" height="13.985" width="41.57" fill="#ddd" stroke="#000" stroke-width=".5"/><path d="M28.451 4.631h24.7" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#a)"/><rect ry="1.228" rx="1.228" y="3.277" x="54.378" height="7.611" width="21.726" fill="#fff" stroke="#000" stroke-width=".5"/><text y="8.632" x="56.992" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="8.467" letter-spacing="0" word-spacing="0" font-family="Consolas" stroke-width=".265"><tspan y="8.632" x="56.992" font-size="4.939">EEPROM</tspan></text><path d="M54.093 9.848H28.126" fill="none" stroke="#e47128" stroke-width=".5" marker-end="url(#b)"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker id="b" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker></defs><rect width="41.57" height="13.985" x="38.123" y=".25" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="-.263" y="8.925" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="-.263" y="8.925" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="93.777" y="8.454" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="93.777" y="8.454" font-size="4.939">original</tspan></text><path d="M28.451 4.634h61.238" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#a)"/><path d="M89.689 9.708H28.45" fill="none" stroke="#e47128" stroke-width=".5" marker-end="url(#b)"/><path d="M43.874 9.708c13.976-.11 6.585 2.298 19.874 2.322 6.623.011 17.253.017 25.88.016" fill="none" stroke="#e47128" stroke-width=".3" stroke-dasharray=".60007511,.30003755"/><text y="11.539" x="60.257" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="3.52" font-family="Consolas" letter-spacing="0" word-spacing="0" fill="#e47128" stroke-width=".11"><tspan y="11.539" x="60.257" font-size="2.053">parity bits</tspan></text></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker id="c" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="b" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(98.669 59.515)"><rect ry="1.228" rx="1.228" y="-59.265" x="-60.546" height="13.985" width="41.57" fill="#ddd" stroke="#000" stroke-width=".5"/><path d="M-70.218-54.88H-8.98" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#a)"/><path d="M-9.213-49.664h-61.33" fill="none" stroke="#e47128" stroke-width=".5" marker-end="url(#b)"/><text y="-50.59" x="-98.932" style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan y="-50.59" x="-98.932" font-size="4.939">decorated</tspan></text><text y="-51.061" x="-4.892" style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan y="-51.061" x="-4.892" font-size="4.939">original</tspan></text><path d="M-54.343-54.88c13.977.108 6.585-2.299 19.874-2.322 6.623-.012 16.862-.018 25.489-.017" fill="none" stroke="#00878f" stroke-width=".3" stroke-dasharray=".60000012,.30000006" marker-end="url(#c)"/><text y="-55.516" x="-37.96" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="3.52" font-family="Consolas" letter-spacing="0" word-spacing="0" fill="#00878f" stroke-width=".11"><tspan y="-55.516" x="-37.96" font-size="2.053">parity bits</tspan></text></g></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker id="c" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker><marker id="b" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker></defs><rect width="41.57" height="13.985" x="38.123" y=".25" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="-.263" y="8.925" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="-.263" y="8.925" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="93.777" y="8.454" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="93.777" y="8.454" font-size="4.939">original</tspan></text><path d="M28.451 4.634h61.238" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#a)"/><path d="M44.326 4.634c13.977.11 6.585-2.298 19.874-2.321 6.623-.012 16.862-.018 25.489-.017" fill="none" stroke="#00878f" stroke-width=".3" stroke-dasharray=".60000012,.30000006" marker-end="url(#b)"/><text y="3.999" x="60.709" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="3.52" font-family="Consolas" letter-spacing="0" word-spacing="0" fill="#00878f" stroke-width=".11"><tspan y="3.999" x="60.709" font-size="2.053">parity bits</tspan></text><path d="M89.689 9.708H28.45" fill="none" stroke="#e47128" stroke-width=".5" marker-end="url(#c)"/><path d="M43.874 9.708c13.976-.11 6.585 2.298 19.874 2.322 6.623.011 17.253.017 25.88.016" fill="none" stroke="#e47128" stroke-width=".3" stroke-dasharray=".60007511,.30003755"/><text y="11.539" x="60.257" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="3.52" font-family="Consolas" letter-spacing="0" word-spacing="0" fill="#e47128" stroke-width=".11"><tspan y="11.539" x="60.257" font-size="2.053">parity bits</tspan></text></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="83.339" viewBox="0 0 115.175 22.05"><defs><marker id="d" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="c" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="b" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(-39.95 -20.829)"><rect width="41.57" height="13.985" x="78.073" y="21.079" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><g fill="none" stroke-width=".5"><path d="M69.4 25.463h61.238" stroke="#00878f" marker-end="url(#a)" transform="translate(-.999)"/><path d="M130.405 30.68H69.076" stroke="#e47128" marker-end="url(#b)" transform="translate(-.999)"/></g><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="39.688" y="29.753" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="39.688" y="29.753" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="133.728" y="29.283" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="133.728" y="29.283" font-size="4.939">original</tspan></text></g><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="90.274" y="65.863" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265" transform="translate(-35.395 -44.826)"><tspan x="90.274" y="65.863" font-size="4.939">log</tspan></text><path d="M109.984 54.716c-12.353.036-13.228 2.364-14.03 7.49" fill="none" stroke="#e47128" stroke-width=".4" marker-end="url(#c)" transform="translate(-35.395 -44.826)"/><path d="M77.615 49.403c12.353.036 14.564 7.643 15.366 12.768" fill="none" stroke="#00878f" stroke-width=".4" marker-end="url(#d)" transform="translate(-35.395 -44.826)"/></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="b" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(-39.95 -20.829)"><rect width="41.57" height="13.985" x="78.073" y="21.079" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><g fill="none" stroke-width=".5"><path d="M69.4 25.463h61.238" stroke="#00878f" marker-end="url(#a)" transform="translate(-.999)"/><path d="M130.405 30.68H69.076" stroke="#e47128" marker-end="url(#b)" transform="translate(-.999)"/></g><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="39.688" y="29.753" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="39.688" y="29.753" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="133.728" y="29.283" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="133.728" y="29.283" font-size="4.939">original</tspan></text></g><g transform="translate(-39.95 -45.962)"><rect ry=".483" rx=".483" y="53.317" x="87.265" height="4.944" width="23.186" fill="#fff" stroke="#e47128" stroke-width=".5"/><text y="57.228" x="91.548" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="4.386" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan y="57.228" x="91.548">buffer</tspan></text></g></svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="83.339" viewBox="0 0 115.175 22.05"><defs><marker id="c" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="b" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(-39.95 -20.829)"><rect width="41.57" height="13.985" x="78.073" y="21.079" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><g fill="none" stroke-width=".5"><path d="M69.4 25.463h61.238" stroke="#00878f" marker-end="url(#a)" transform="translate(-.999)"/><path d="M130.405 30.68H69.076" stroke="#e47128" marker-end="url(#b)" transform="translate(-.999)"/></g><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="39.688" y="29.753" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="39.688" y="29.753" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="133.728" y="29.283" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="133.728" y="29.283" font-size="4.939">original</tspan></text></g><text y="80.982" x="120.512" style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265" transform="translate(-65.633 -59.945)"><tspan y="80.982" x="120.512" font-size="4.939">log</tspan></text><path d="M140.223 69.835c-12.353.036-13.229 2.364-14.03 7.49" fill="none" stroke="#e47128" stroke-width=".4" marker-end="url(#c)" transform="translate(-65.633 -59.945)"/></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker id="a" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker></defs><rect ry="1.228" rx="1.228" y=".25" x="38.123" height="13.985" width="41.57" fill="#ddd" stroke="#000" stroke-width=".5"/><path d="M28.451 4.631h24.7" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#a)"/><rect ry="1.228" rx="1.228" y="3.277" x="54.378" height="7.611" width="21.726" fill="#fff" stroke="#000" stroke-width=".5"/><text y="8.632" x="56.992" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan y="8.632" x="56.992" font-size="4.939">String</tspan></text></svg>

Before

Width:  |  Height:  |  Size: 984 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker id="a" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker id="b" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><rect ry="1.228" rx="1.228" y=".25" x="38.123" height="13.985" width="41.57" fill="#ddd" stroke="#000" stroke-width=".5"/><path d="M28.451 4.631h24.7" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#a)"/><rect ry="1.228" rx="1.228" y="3.277" x="54.378" height="7.611" width="21.726" fill="#fff" stroke="#000" stroke-width=".5"/><text y="8.632" x="56.992" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan y="8.632" x="56.992" font-size="4.939">String</tspan></text><path d="M54.093 9.848H28.126" fill="none" stroke="#e47128" stroke-width=".5" marker-end="url(#b)"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="54.747" viewBox="0 0 115.175 14.485"><defs><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="b" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(-39.95 -20.829)"><rect width="41.57" height="13.985" x="78.073" y="21.079" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><g fill="none" stroke-width=".5"><path d="M69.4 25.463h61.238" stroke="#00878f" marker-end="url(#a)" transform="translate(-.999)"/><path d="M130.405 30.68H69.076" stroke="#e47128" marker-end="url(#b)" transform="translate(-.999)"/></g><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="39.688" y="29.753" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="39.688" y="29.753" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="133.728" y="29.283" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="133.728" y="29.283" font-size="4.939">original</tspan></text></g><g transform="translate(-39.95 -51.12)"><rect ry=".483" rx=".483" y="53.317" x="87.265" height="4.944" width="23.186" fill="#fff" stroke="#00878f" stroke-width=".5"/><text y="57.228" x="91.548" style="line-height:125%;-inkscape-font-specification:Consolas" font-weight="400" font-size="4.386" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan y="57.228" x="91.548">buffer</tspan></text></g></svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="435.307" height="83.337" viewBox="0 0 115.175 22.05"><defs><marker orient="auto" refY="0" refX="0" id="c" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker><marker orient="auto" refY="0" refX="0" id="b" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(-39.95 -20.829)"><rect width="41.57" height="13.985" x="78.073" y="21.079" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><g fill="none" stroke-width=".5"><path d="M69.4 25.463h61.238" stroke="#00878f" marker-end="url(#a)" transform="translate(-.999)"/><path d="M130.405 30.68H69.076" stroke="#e47128" marker-end="url(#b)" transform="translate(-.999)"/></g><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="39.688" y="29.753" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="39.688" y="29.753" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="133.728" y="29.283" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="133.728" y="29.283" font-size="4.939">original</tspan></text></g><text y="128.607" x="100.101" style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265" transform="translate(-45.222 -107.57)"><tspan y="128.607" x="100.101" font-size="4.939">log</tspan></text><path d="M87.442 112.147c12.353.036 14.565 7.643 15.367 12.769" fill="none" stroke="#00878f" stroke-width=".4" marker-end="url(#c)" transform="translate(-45.222 -107.57)"/></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="435.307" height="81.808" viewBox="0 0 115.175 21.645"><defs><marker orient="auto" refY="0" refX="0" id="c" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#848484" fill-rule="evenodd" stroke="#848484" stroke-width=".375" stroke-linejoin="round"/></marker><marker id="a" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#e47128" fill-rule="evenodd" stroke="#e47128" stroke-width=".375" stroke-linejoin="round"/></marker><marker id="b" refX="0" refY="0" orient="auto" overflow="visible"><path d="M-5.231-2.42L1.324-.01-5.23 2.401c1.047-1.423 1.041-3.37 0-4.821z" fill="#00878f" fill-rule="evenodd" stroke="#00878f" stroke-width=".375" stroke-linejoin="round"/></marker></defs><g transform="translate(-39.95 -21.077)"><rect width="41.57" height="13.985" x="78.073" y="28.487" rx="1.228" ry="1.228" fill="#ddd" stroke="#000" stroke-width=".5"/><path d="M129.407 38.617h-61.33" fill="none" stroke="#e47128" stroke-width=".5" marker-end="url(#a)"/><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="39.688" y="37.691" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="39.688" y="37.691" font-size="4.939">decorated</tspan></text><text style="line-height:125%;-inkscape-font-specification:Consolas;fill:#777" x="133.728" y="37.221" font-weight="400" font-size="8.467" font-family="Consolas" letter-spacing="0" word-spacing="0" stroke-width=".265"><tspan x="133.728" y="37.221" font-size="4.939">original</tspan></text><path d="M68.62 33.947H93.42c3.95 0 3.568-3.143 2.08-3.137-1.488.006-2.08 3.137 1.58 3.144l.254-.007c3.766-.096 3.368-3.125 1.88-3.119-1.49.006-1.88 3.12 1.541 3.12h.215c3.95 0 3.569-3.144 2.08-3.138-1.488.006-2.08 3.137 1.87 3.137h24.655" fill="none" stroke="#00878f" stroke-width=".5" marker-end="url(#b)"/><path d="M103.025 30.448v-5.364" id="d" fill="none" fill-rule="evenodd" stroke="#848484" stroke-width=".249" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="4" stroke-dasharray=".24941605,.24941605" stroke-dashoffset="0" stroke-opacity="1" marker-end="url(#c)"/><text style="line-height:125%;-inkscape-font-specification:Consolas" x="93.793" y="23.561" font-weight="400" font-size="3.416" font-family="Consolas" letter-spacing="0" word-spacing="0" fill="#848484" stroke-width=".107"><tspan x="93.793" y="23.561">wait()</tspan></text><use x="0" y="0" xlink:href="#d" id="e" transform="translate(-3.807)" width="100%" height="100%"/><use xlink:href="#e" transform="translate(-3.808)" width="100%" height="100%"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1,137 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "FailingAllocator.hpp"
#include "StreamUtils/Prints/BufferingPrint.hpp"
#include "StreamUtils/Prints/SpyingPrint.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("BufferingPrint") {
StringPrint target;
StringPrint log;
SpyingPrint spy{target, log};
GIVEN("capacity is 4") {
BufferingPrint bufferingPrint{spy, 4};
SUBCASE("flush() calls write()") {
bufferingPrint.write("ABC", 3);
bufferingPrint.flush();
#if STREAMUTILS_PRINT_FLUSH_EXISTS
CHECK(log.str() ==
"write('ABC', 3) -> 3"
"flush()");
#else
CHECK(log.str() == "write('ABC', 3) -> 3");
#endif
}
GIVEN("the buffer is empty") {
SUBCASE("write(uint8_t)") {
int n = bufferingPrint.write('A');
CHECK(n == 1);
CHECK(log.str() == "");
}
SUBCASE("write(uint8_t) should flush") {
bufferingPrint.write('A');
bufferingPrint.write('B');
bufferingPrint.write('C');
bufferingPrint.write('D');
bufferingPrint.write('E');
CHECK(log.str() == "write('ABCD', 4) -> 4");
}
SUBCASE("write(char*,3) goes in buffer") {
size_t n = bufferingPrint.write("ABC", 3);
CHECK(n == 3);
CHECK(log.str() == "");
}
SUBCASE("write(char*,4) bypasses buffer") {
size_t n = bufferingPrint.write("ABCD", 4);
CHECK(n == 4);
CHECK(log.str() == "write('ABCD', 4) -> 4");
}
SUBCASE("write(char*,2) bypasses buffer") {
size_t n = bufferingPrint.write("ABCD", 4);
CHECK(n == 4);
CHECK(log.str() == "write('ABCD', 4) -> 4");
}
}
GIVEN("one byte in the buffer") {
bufferingPrint.write('A');
SUBCASE("write(char*,3) goes in buffer and flush") {
size_t n = bufferingPrint.write("BCD", 3);
CHECK(n == 3);
CHECK(log.str() == "write('ABCD', 4) -> 4");
}
SUBCASE("write(char*,7) bypasses") {
size_t n = bufferingPrint.write("BCDEFGH", 7);
CHECK(n == 7);
CHECK(log.str() ==
"write('ABCD', 4) -> 4"
"write('EFGH', 4) -> 4");
}
}
}
GIVEN("capacity is 0") {
BufferingPrint bufferingPrint{spy, 0};
// SUBCASE("capacity()") {
// CHECK(bufferingPrint.capacity() == 0);
// }
SUBCASE("write(uint8_t) forwards to target") {
int n = bufferingPrint.write('X');
CHECK(n == 1);
CHECK(log.str() == "write('X') -> 1");
}
SUBCASE("write(char*,1) forwards to target") {
int n = bufferingPrint.write("A", 1);
CHECK(n == 1);
CHECK(log.str() == "write('A', 1) -> 1");
}
SUBCASE("flush()") {
bufferingPrint.flush();
#if STREAMUTILS_PRINT_FLUSH_EXISTS
CHECK(log.str() == "flush()");
#else
CHECK(log.str() == "");
#endif
}
}
SUBCASE("Destructor should flush") {
{
BufferingPrint bufferingPrint{spy, 10};
bufferingPrint.write("ABC", 3);
}
CHECK(log.str() == "write('ABC', 3) -> 3");
}
}

View File

@@ -1,104 +0,0 @@
# StreamUtils - github.com/bblanchon/ArduinoStreamUtils
# Copyright Benoit Blanchon 2019-2021
# MIT License
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
add_compile_options(-Wall -Wextra -Werror -Wundef)
endif()
set(SOURCES
BufferingPrintTest.cpp
EepromStreamTest.cpp
FailingAllocator.hpp
HammingClientTest.cpp
HammingDecodingClientTest.cpp
HammingDecodingStreamTest.cpp
HammingEncodingClientTest.cpp
HammingEncodingStreamTest.cpp
HammingPrintTest.cpp
HammingStreamTest.cpp
LoggingClientTest.cpp
LoggingPrintTest.cpp
LoggingStreamTest.cpp
MemoryStreamTest.cpp
ReadBufferingClientTest.cpp
ReadBufferingStreamTest.cpp
ReadLoggingClientTest.cpp
ReadLoggingStreamTest.cpp
ReadThrottlingStreamTest.cpp
StringPrintTest.cpp
StringStreamTest.cpp
WaitingPrintTest.cpp
WriteBufferingClientTest.cpp
WriteBufferingStreamTest.cpp
WriteLoggingClientTest.cpp
WriteLoggingStreamTest.cpp
WriteWaitingClientTest.cpp
WriteWaitingStreamTest.cpp
doctest.h
main.cpp
)
########## AVR ##########
add_subdirectory(cores/avr)
add_executable(StreamUtilsTestAvr ${SOURCES})
target_link_libraries(StreamUtilsTestAvr AvrCore)
add_test(Avr StreamUtilsTestAvr)
########## ESP32 ##########
add_subdirectory(cores/esp32)
add_executable(StreamUtilsTestEsp32 ${SOURCES})
target_link_libraries(StreamUtilsTestEsp32 Esp32Core)
add_test(Esp32 StreamUtilsTestEsp32)
########## ESP8266 ##########
add_subdirectory(cores/esp8266)
add_executable(StreamUtilsTestEsp8266 ${SOURCES})
target_link_libraries(StreamUtilsTestEsp8266 Esp8266Core)
add_test(Esp8266 StreamUtilsTestEsp8266)
########## NRF52 ##########
add_subdirectory(cores/nrf52)
add_executable(StreamUtilsTestNrf52 ${SOURCES})
target_link_libraries(StreamUtilsTestNrf52 Nrf52Core)
add_test(Nrf52 StreamUtilsTestNrf52)
########## SAMD ##########
add_subdirectory(cores/samd)
add_executable(StreamUtilsTestSamd ${SOURCES})
target_link_libraries(StreamUtilsTestSamd SamdCore)
add_test(Samd StreamUtilsTestSamd)
########## STM32 ##########
add_subdirectory(cores/stm32)
add_executable(StreamUtilsTestStm32 ${SOURCES})
target_link_libraries(StreamUtilsTestStm32 Stm32Core)
add_test(Stm32 StreamUtilsTestStm32)
########## Teensy ##########
add_subdirectory(cores/teensy)
add_executable(StreamUtilsTestTeensy ${SOURCES})
target_link_libraries(StreamUtilsTestTeensy TeensyCore)
add_test(Teensy StreamUtilsTestTeensy)

View File

@@ -1,57 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "StreamUtils/Streams/EepromStream.hpp"
#if STREAMUTILS_ENABLE_EEPROM
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("EepromStream") {
SUBCASE("available()") {
EepromStream s(42, 84);
CHECK(s.available() == 84);
}
SUBCASE("write(uint8_t)") {
EepromStream s(0, 2);
CHECK(s.write('a') == 1);
CHECK(s.write('b') == 1);
CHECK(s.write('c') == 0);
CHECK(s.write('d') == 0);
s.flush();
CHECK(s.readString() == "ab");
}
SUBCASE("write(const uint8_t *, size_t)") {
EepromStream s(0, 5);
CHECK(s.write("abc", 3) == 3);
CHECK(s.write("def", 3) == 2);
CHECK(s.write("ghi", 3) == 0);
s.flush();
CHECK(s.readString() == "abcde");
}
SUBCASE("read()") {
EepromStream s(0, 2);
s.write("ab", 2);
CHECK(s.read() == 'a');
CHECK(s.read() == 'b');
CHECK(s.read() == -1);
}
SUBCASE("peek()") {
EepromStream s(0, 2);
s.write("ab", 2);
CHECK(s.peek() == 'a');
CHECK(s.peek() == 'a');
s.read();
CHECK(s.peek() == 'b');
s.read();
CHECK(s.peek() == -1);
}
}
#endif

View File

@@ -1,14 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <stdlib.h> // size_t
struct FailingAllocator {
void* allocate(size_t) {
return nullptr;
}
void deallocate(void*) {}
};

View File

@@ -1,30 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "SpyingAllocator.hpp"
#include "StreamUtils/Clients/HammingClient.hpp"
#include "StreamUtils/Clients/MemoryClient.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("HammingClient") {
MemoryClient upstream(64);
HammingClient<7, 4> client{upstream};
SUBCASE("read() decodes") {
upstream.print("Tq");
CHECK(client.read() == 'A');
}
SUBCASE("write() encodes") {
client.write('A');
CHECK(upstream.readString() == "Tq");
}
}

View File

@@ -1,137 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "SpyingAllocator.hpp"
#include "StreamUtils/Clients/HammingDecodingClient.hpp"
#include "StreamUtils/Clients/MemoryClient.hpp"
#include "StreamUtils/Clients/SpyingClient.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("HammingDecodingClient") {
MemoryClient upstream(64);
StringPrint log;
SpyingClient spy{upstream, log};
SpyingAllocator allocator{log};
BasicHammingDecodingClient<7, 4, SpyingAllocator&> client{spy, allocator};
SUBCASE("read() with small buffer") {
uint8_t buffer[8];
SUBCASE("empty input") {
size_t result = client.read(buffer, sizeof(buffer));
CHECK(result == 0);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "read(16) -> 0 [timeout]");
#endif
}
SUBCASE("decodes input") {
upstream.print("TqTb");
size_t result = client.read(buffer, sizeof(buffer));
CHECK(result == 2);
CHECK(std::string((char*)buffer, result) == "AB");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "read(16) -> 4 [timeout]");
#endif
}
SUBCASE("includes byte loaded by peek()") {
upstream.print("TqTb");
client.peek();
log.clear();
size_t result = client.read(buffer, sizeof(buffer));
CHECK(result == 2);
CHECK(std::string((char*)buffer, result) == "AB");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "read(15) -> 3 [timeout]");
#endif
}
SUBCASE("stores dangling byte") {
upstream.print("TqT");
size_t result = client.read(buffer, sizeof(buffer));
CHECK(result == 1);
CHECK(std::string((char*)buffer, result) == "A");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "read(16) -> 3 [timeout]");
#endif
log.clear();
upstream.print("b");
CHECK(client.peek() == 'B');
CHECK(log.str() == "peek() -> 98");
}
SUBCASE("clears the byte loaded by peek") {
upstream.print("TqTb");
client.peek();
client.read(buffer, sizeof(buffer));
client.peek();
CHECK(log.str() ==
"read() -> 84"
"peek() -> 113"
"read(15) -> 3 [timeout]"
"read() -> -1");
}
}
SUBCASE("read() with large buffer") {
uint8_t buffer[32];
SUBCASE("empty input") {
size_t result = client.read(buffer, sizeof(buffer));
CHECK(result == 0);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"allocate(64) -> ptr"
"read(64) -> 0 [timeout]"
"deallocate(ptr)");
#endif
}
SUBCASE("decodes input") {
upstream.print("TqTb");
size_t result = client.read(buffer, sizeof(buffer));
CHECK(result == 2);
CHECK(std::string((char*)buffer, result) == "AB");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"allocate(64) -> ptr"
"read(64) -> 4 [timeout]"
"deallocate(ptr)");
#endif
}
SUBCASE("uses input buffer if allocation fails") {
upstream.print("TqTb");
allocator.forceFail = true;
size_t result = client.read(buffer, sizeof(buffer));
CHECK(result == 2);
CHECK(std::string((char*)buffer, result) == "AB");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"allocate(64) -> null"
"read(32) -> 4 [timeout]");
#endif
}
}
}

View File

@@ -1,290 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "SpyingAllocator.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "StreamUtils/Streams/HammingDecodingStream.hpp"
#include "StreamUtils/Streams/SpyingStream.hpp"
#include "StreamUtils/Streams/StringStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("HammingDecodingStream") {
StringStream upstream;
StringPrint log;
SpyingStream spy{upstream, log};
SpyingAllocator allocator{log};
BasicHammingDecodingStream<7, 4, SpyingAllocator&> stream{spy, allocator};
SUBCASE("available()") {
SUBCASE("empty input") {
CHECK(stream.available() == 0);
CHECK(log.str() == "available() -> 0");
}
SUBCASE("even number of bytes") {
upstream.print("ABCDEFGH");
CHECK(stream.available() == 4);
CHECK(log.str() == "available() -> 8");
}
SUBCASE("odd number of bytes") {
upstream.print("ABCDEFGHI");
CHECK(stream.available() == 4);
CHECK(log.str() == "available() -> 9");
}
SUBCASE("even number of bytes after peek") {
upstream.print("ABCDEFGH");
stream.peek();
log.clear();
CHECK(stream.available() == 4);
CHECK(log.str() == "available() -> 7");
}
SUBCASE("odd number of bytes after peek") {
upstream.print("ABCDEFGHI");
stream.peek();
log.clear();
CHECK(stream.available() == 4);
CHECK(log.str() == "available() -> 8");
}
}
SUBCASE("peek()") {
SUBCASE("returns -1 when empty") {
int result = stream.peek();
CHECK(result == -1);
CHECK(log.str() == "read() -> -1");
}
SUBCASE("returns -1 when only one byte in input") {
upstream.print("A");
int result = stream.peek();
CHECK(result == -1);
CHECK(log.str() ==
"read() -> 65"
"peek() -> -1");
}
SUBCASE("returns decoded value") {
upstream.print("Tq");
int result = stream.peek();
CHECK(result == 'A');
CHECK(log.str() ==
"read() -> 84"
"peek() -> 113");
}
SUBCASE("doesn't call read() the second time") {
upstream.print("A");
stream.peek();
log.clear();
int result = stream.peek();
CHECK(result == -1);
CHECK(log.str() == "peek() -> -1");
}
}
SUBCASE("read()") {
SUBCASE("returns -1 if empty") {
int result = stream.read();
CHECK(result == -1);
CHECK(log.str() == "read() -> -1");
}
SUBCASE("returns -1 if only one byte in input") {
upstream.print("A");
int result = stream.read();
CHECK(result == -1);
CHECK(log.str() ==
"read() -> 65"
"read() -> -1");
}
SUBCASE("returns decoded value if two bytes in input") {
upstream.print("Tq");
int result = stream.read();
CHECK(result == 'A');
CHECK(log.str() ==
"read() -> 84"
"read() -> 113");
}
SUBCASE("reuses the byte read by peek()") {
upstream.print("Tq");
stream.peek();
log.clear();
int result = stream.read();
CHECK(result == 'A');
CHECK(log.str() == "read() -> 113");
}
SUBCASE("reuses the byte read by previous call") {
upstream.print("T");
stream.read();
upstream.print("q");
log.clear();
int result = stream.read();
CHECK(result == 'A');
CHECK(log.str() == "read() -> 113");
}
SUBCASE("flushes the buffered byte") {
upstream.print("TqTb");
CHECK(stream.read() == 'A');
CHECK(stream.read() == 'B');
CHECK(log.str() ==
"read() -> 84"
"read() -> 113"
"read() -> 84"
"read() -> 98");
}
}
SUBCASE("readBytes() with small buffer") {
char buffer[8];
SUBCASE("empty input") {
size_t result = stream.readBytes(buffer, sizeof(buffer));
CHECK(result == 0);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(16) -> 0 [timeout]");
#endif
}
SUBCASE("decodes input") {
upstream.print("TqTb");
size_t result = stream.readBytes(buffer, sizeof(buffer));
CHECK(result == 2);
CHECK(std::string(buffer, result) == "AB");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(16) -> 4 [timeout]");
#endif
}
SUBCASE("includes byte loaded by peek()") {
upstream.print("TqTb");
stream.peek();
log.clear();
size_t result = stream.readBytes(buffer, sizeof(buffer));
CHECK(result == 2);
CHECK(std::string(buffer, result) == "AB");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(15) -> 3 [timeout]");
#endif
}
SUBCASE("stores dangling byte") {
upstream.print("TqT");
size_t result = stream.readBytes(buffer, sizeof(buffer));
CHECK(result == 1);
CHECK(std::string(buffer, result) == "A");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(16) -> 3 [timeout]");
#endif
log.clear();
upstream.print("b");
CHECK(stream.peek() == 'B');
CHECK(log.str() == "peek() -> 98");
}
SUBCASE("clears the byte loaded by peek") {
upstream.print("TqTb");
stream.peek();
stream.readBytes(buffer, sizeof(buffer));
CHECK(stream.peek() == -1);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"read() -> 84"
"peek() -> 113"
"readBytes(15) -> 3 [timeout]"
"read() -> -1");
#endif
}
}
SUBCASE("readBytes() with large buffer") {
char buffer[32];
SUBCASE("empty input") {
size_t result = stream.readBytes(buffer, sizeof(buffer));
CHECK(result == 0);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"allocate(64) -> ptr"
"readBytes(64) -> 0 [timeout]"
"deallocate(ptr)");
#endif
}
SUBCASE("decodes input") {
upstream.print("TqTb");
size_t result = stream.readBytes(buffer, sizeof(buffer));
CHECK(result == 2);
CHECK(std::string(buffer, result) == "AB");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"allocate(64) -> ptr"
"readBytes(64) -> 4 [timeout]"
"deallocate(ptr)");
#endif
}
SUBCASE("uses input buffer if allocation fails") {
upstream.print("TqTb");
allocator.forceFail = true;
size_t result = stream.readBytes(buffer, sizeof(buffer));
CHECK(result == 2);
CHECK(std::string(buffer, result) == "AB");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"allocate(64) -> null"
"readBytes(32) -> 4 [timeout]");
#endif
}
}
SUBCASE("flush()") {
stream.flush();
CHECK(log.str() == "flush()");
}
}

View File

@@ -1,30 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "SpyingAllocator.hpp"
#include "StreamUtils/Clients/HammingEncodingClient.hpp"
#include "StreamUtils/Clients/MemoryClient.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("HammingEncodingClient") {
MemoryClient upstream(64);
HammingEncodingClient<7, 4> client{upstream};
SUBCASE("read() forwards upstream data") {
upstream.print("A");
CHECK(client.read() == 'A');
}
SUBCASE("write() encodes") {
client.write('A');
CHECK(upstream.readString() == "Tq");
}
}

View File

@@ -1,30 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "SpyingAllocator.hpp"
#include "StreamUtils/Streams/HammingEncodingStream.hpp"
#include "StreamUtils/Streams/MemoryStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("HammingEncodingStream") {
MemoryStream upstream(64);
HammingEncodingStream<7, 4> stream{upstream};
SUBCASE("read() forwards upstream data") {
upstream.print("A");
CHECK(stream.read() == 'A');
}
SUBCASE("write() encodes") {
stream.write('A');
CHECK(upstream.readString() == "Tq");
}
}

View File

@@ -1,202 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "SpyingAllocator.hpp"
#include "StreamUtils/Prints/HammingPrint.hpp"
#include "StreamUtils/Prints/SpyingPrint.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "StreamUtils/Streams/MemoryStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("HammingPrint") {
MemoryStream upstream(4);
StringPrint log;
SpyingPrint spy{upstream, log};
SpyingAllocator allocator{log};
BasicHammingPrint<7, 4, SpyingAllocator&> print{spy, allocator};
SUBCASE("write(char*, size_t)") {
SUBCASE("stops if even byte fails") {
CHECK(print.print("ABA") == 2);
print.write('A'); // try to flush remainder
CHECK(log.str() ==
"write('TqTbTq', 6) -> 4"
"write('T') -> 0" // no remainder
);
}
SUBCASE("saves remainder if odd byte fails") {
upstream.print("?");
CHECK(print.print("ABA") == 2);
print.write('A'); // try to flush remainder
CHECK(log.str() ==
"write('TqTbTq', 6) -> 3"
"write('b') -> 0" // remainder!!
);
}
SUBCASE("writes remainder first") {
upstream.print("???");
print.write('A'); // add remainder
log.clear();
upstream.readString();
CHECK(print.print("ABA") == 2);
CHECK(log.str() ==
"write('q') -> 1"
"write('TqTbTq', 6) -> 3");
}
SUBCASE("stops if remainder fails") {
upstream.print("???");
print.write('A'); // add remainder
log.clear();
CHECK(print.print("ABA") == 0);
CHECK(log.str() == "write('q') -> 0");
}
SUBCASE("allocates in stack when buffer is small") {
print.write("ABABABABABABABAB", 16);
CHECK(log.str() == "write('TqTbTqTbTqTbTqTbTqTbTqTbTqTbTqTb', 32) -> 4");
}
SUBCASE("allocates in heap when buffer is large") {
print.write("ABABABABABABABABA", 17);
CHECK(log.str() ==
"allocate(34) -> ptr"
"write('TqTbTqTbTqTbTqTbTqTbTqTbTqTbTqTbTq', 34) -> 4"
"deallocate(ptr)");
}
SUBCASE("falls back to stack if heap fails") {
allocator.forceFail = true;
print.write("ABABABABABABABABA", 17);
CHECK(log.str() ==
"allocate(34) -> null"
"write('TqTbTqTbTqTbTqTbTqTbTqTbTqTbTqTb', 32) -> 4");
}
}
SUBCASE("write(char)") {
SUBCASE("writes both bytes") {
CHECK(print.write('A') == 1);
CHECK(upstream.readString() == "Tq");
CHECK(log.str() ==
"write('T') -> 1"
"write('q') -> 1");
}
SUBCASE("stops if first by fails") {
upstream.print("????");
CHECK(print.write('A') == 0);
print.write('A'); // try to flush remainder
CHECK(log.str() ==
"write('T') -> 0"
"write('T') -> 0" // no remainder
);
}
SUBCASE("saves remainder if second by fails") {
upstream.print("???");
CHECK(print.write('A') == 1);
print.write('A'); // try to flush remainder
CHECK(log.str() ==
"write('T') -> 1"
"write('q') -> 0"
"write('q') -> 0" // remainder!!
);
}
SUBCASE("writes remainder first") {
upstream.print("???");
print.write('A'); // add remainder
log.clear();
upstream.readString();
CHECK(print.write('A') == 1);
CHECK(log.str() ==
"write('q') -> 1"
"write('T') -> 1"
"write('q') -> 1");
}
SUBCASE("stops if remainder fails") {
upstream.print("???");
print.write('A'); // add remainder
log.clear();
CHECK(print.write('A') == 0);
print.write('A'); // try to flush remainder
CHECK(log.str() ==
"write('q') -> 0"
"write('q') -> 0" // remainder!!
);
}
SUBCASE("resets remainder") {
upstream.print("???");
print.write('A'); // add remainder
log.clear();
upstream.read();
CHECK(print.write('A') == 0);
print.write('A'); // try to flush remainder
CHECK(log.str() ==
"write('q') -> 1"
"write('T') -> 0"
"write('T') -> 0" // no remainder
);
}
}
#if STREAMUTILS_PRINT_FLUSH_EXISTS
SUBCASE("flush() writes remainder") {
upstream.print("???");
print.write('A'); // add remainder
log.clear();
upstream.read();
print.flush();
CHECK(log.str() ==
"write('q') -> 1"
"flush()" // no remainder
);
}
#endif
SUBCASE("destructor flushes remainder") {
{
BasicHammingPrint<7, 4, SpyingAllocator&> print{spy, allocator};
upstream.print("???");
print.write('A'); // add remainder
log.clear();
}
CHECK(log.str() == "write('q') -> 0");
}
}

View File

@@ -1,30 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "SpyingAllocator.hpp"
#include "StreamUtils/Streams/HammingStream.hpp"
#include "StreamUtils/Streams/MemoryStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("HammingStream") {
MemoryStream upstream(64);
HammingStream<7, 4> stream{upstream};
SUBCASE("read() decodes") {
upstream.print("Tq");
CHECK(stream.read() == 'A');
}
SUBCASE("write() encodes") {
stream.write('A');
CHECK(upstream.readString() == "Tq");
}
}

View File

@@ -1,138 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "StreamUtils/Clients/LoggingClient.hpp"
#include "StreamUtils/Clients/MemoryClient.hpp"
#include "StreamUtils/Clients/SpyingClient.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("LoggingClient") {
MemoryClient target(4);
StringPrint log;
SpyingClient spy{target, log};
StringPrint output;
LoggingClient loggingClient{spy, output};
SUBCASE("available()") {
target.print("ABC");
size_t n = loggingClient.available();
CHECK(n == 3);
CHECK(log.str() == "available() -> 3");
CHECK(output.str() == "");
}
SUBCASE("connect(IPAddress)") {
int n = loggingClient.connect(IPAddress("1.2.3.4"), 80);
CHECK(n == 1);
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
CHECK(output.str() == "");
}
SUBCASE("connect(const char*)") {
int n = loggingClient.connect("1.2.3.4", 80);
CHECK(n == 1);
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
CHECK(output.str() == "");
}
SUBCASE("connected()") {
uint8_t n = loggingClient.connected();
CHECK(n == false);
CHECK(log.str() == "connected() -> 0");
CHECK(output.str() == "");
}
SUBCASE("stop()") {
loggingClient.stop();
CHECK(log.str() == "stop()");
CHECK(output.str() == "");
}
SUBCASE("operator bool()") {
bool n = loggingClient.operator bool();
CHECK(n == true);
CHECK(log.str() == "operator bool() -> true");
CHECK(output.str() == "");
}
SUBCASE("peek()") {
target.print("ABC");
int n = loggingClient.peek();
CHECK(n == 'A');
CHECK(log.str() == "peek() -> 65");
CHECK(output.str() == "");
}
SUBCASE("read()") {
target.print("ABC");
int n = loggingClient.read();
CHECK(n == 'A');
CHECK(log.str() == "read() -> 65");
CHECK(output.str() == "A");
}
SUBCASE("read(uint8_t*,size_t)") {
target.print("ABC");
uint8_t s[4] = {0};
size_t n = loggingClient.read(s, 4);
CHECK(n == 3);
CHECK(log.str() == "read(4) -> 3 [timeout]");
CHECK(output.str() == "ABC");
}
SUBCASE("readBytes()") {
target.print("ABC");
char s[4] = {0};
size_t n = loggingClient.readBytes(s, 4);
CHECK(n == 3);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(4) -> 3 [timeout]");
#endif
CHECK(output.str() == "ABC");
}
SUBCASE("write(char)") {
int n = loggingClient.write('A');
CHECK(n == 1);
CHECK(log.str() == "write('A') -> 1");
CHECK(output.str() == "A");
}
SUBCASE("write(char*,size_t)") {
int n = loggingClient.write("ABCDEF", 6);
CHECK(n == 4);
CHECK(log.str() == "write('ABCDEF', 6) -> 4");
CHECK(output.str() == "ABCD");
}
SUBCASE("flush()") {
loggingClient.flush();
CHECK(output.str() == "");
CHECK(log.str() == "flush()");
}
}

View File

@@ -1,41 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "StreamUtils/Prints/LoggingPrint.hpp"
#include "StreamUtils/Streams/MemoryStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("LoggingPrint") {
MemoryStream primary(4);
MemoryStream secondary(64);
LoggingPrint loggingPrint{primary, secondary};
SUBCASE("write(char)") {
int n = loggingPrint.write('A');
CHECK(n == 1);
CHECK(primary.readString() == "A");
CHECK(secondary.readString() == "A");
}
SUBCASE("write(char*,size_t)") {
int n = loggingPrint.write("ABCDEF", 6);
CHECK(n == 4);
CHECK(primary.readString() == "ABCD");
CHECK(secondary.readString() == "ABCD");
}
#if STREAMUTILS_PRINT_FLUSH_EXISTS
SUBCASE("flush()") {
loggingPrint.write("AB", 2);
REQUIRE(primary.available() == 2);
loggingPrint.flush();
REQUIRE(primary.available() == 0);
}
#endif
}

View File

@@ -1,93 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "StreamUtils/Prints/StringPrint.hpp"
#include "StreamUtils/Streams/LoggingStream.hpp"
#include "StreamUtils/Streams/MemoryStream.hpp"
#include "StreamUtils/Streams/SpyingStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("LoggingStream") {
MemoryStream upstream{4};
StringPrint output;
StringPrint log;
SpyingStream upstreamSpy{upstream, log};
LoggingStream loggingStream{upstreamSpy, output};
// upstream -> upstreamSpy -> loggingStream -> output
// |
// v
// log
SUBCASE("available()") {
upstream.print("ABC");
size_t n = loggingStream.available();
CHECK(n == 3);
CHECK(log.str() == "available() -> 3");
CHECK(output.str() == "");
}
SUBCASE("peek()") {
upstream.print("ABC");
int n = loggingStream.peek();
CHECK(n == 'A');
CHECK(log.str() == "peek() -> 65");
CHECK(output.str() == "");
}
SUBCASE("read()") {
upstream.print("ABC");
int n = loggingStream.read();
CHECK(n == 'A');
CHECK(log.str() == "read() -> 65");
CHECK(output.str() == "A");
}
SUBCASE("readBytes()") {
upstream.print("ABC");
char s[4] = {0};
size_t n = loggingStream.readBytes(s, 4);
CHECK(n == 3);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(4) -> 3 [timeout]");
#endif
CHECK(output.str() == "ABC");
}
SUBCASE("write(char)") {
int n = loggingStream.write('A');
CHECK(n == 1);
CHECK(log.str() == "write('A') -> 1");
CHECK(output.str() == "A");
}
SUBCASE("write(char*,size_t)") {
int n = loggingStream.write("ABCDEF", 6);
CHECK(n == 4);
CHECK(log.str() == "write('ABCDEF', 6) -> 4");
CHECK(output.str() == "ABCD");
}
SUBCASE("flush()") {
loggingStream.flush();
CHECK(log.str() == "flush()");
CHECK(output.str() == "");
}
}

View File

@@ -1,116 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "StreamUtils/Streams/MemoryStream.hpp"
#include "StreamUtils/Streams/SpyingStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("MemoryStream") {
MemoryStream stream(4);
WHEN("stream is empty") {
THEN("available() return 0") {
CHECK(stream.available() == 0);
}
THEN("write(uint8) returns 1") {
CHECK(stream.write('A') == 1);
}
THEN("write(\"ABCD\",4) returns 4") {
CHECK(stream.write("ABCD", 4) == 4);
}
THEN("write(uint8*,8) returns 4") {
CHECK(stream.write("ABCDEFGH", 8) == 4);
}
THEN("read() return -1") {
CHECK(stream.read() == -1);
}
THEN("peek() return -1") {
CHECK(stream.peek() == -1);
}
}
WHEN("stream is full") {
stream.print("ABCD");
THEN("available() return 4") {
CHECK(stream.available() == 4);
}
THEN("write(uint8) returns 0") {
CHECK(stream.write('A') == 0);
}
THEN("write(\"ABCD\",4) returns 0") {
CHECK(stream.write("ABCD", 4) == 0);
}
THEN("read() returns the next value") {
CHECK(stream.read() == 'A');
CHECK(stream.read() == 'B');
}
THEN("read(uint8_t*,size_t) extracts the next bytes") {
char data[5] = {0};
CHECK(stream.readBytes(data, 4) == 4);
CHECK(data == std::string("ABCD"));
}
THEN("peek() returns the first value") {
CHECK(stream.peek() == 'A');
CHECK(stream.peek() == 'A');
}
SUBCASE("read() makes room for one byte") {
stream.read(); // make room
REQUIRE(stream.available() == 3);
stream.write('E'); // write at the beginning
REQUIRE(stream.available() == 4);
char data[5] = {0};
stream.readBytes(data, 4);
CHECK(data == std::string("BCDE"));
}
}
WHEN("lower half is filled") {
stream.print("AB");
THEN("available() return 2") {
CHECK(stream.available() == 2);
}
THEN("write(uint8) returns 1") {
CHECK(stream.write('C') == 1);
}
THEN("write(\"ABCD\",4) returns 2") {
CHECK(stream.write("ABCD", 4) == 2);
}
THEN("read() returns the next value") {
CHECK(stream.read() == 'A');
CHECK(stream.read() == 'B');
}
THEN("read(uint8_t*,size_t) extracts the next bytes") {
char data[5] = {0};
CHECK(stream.readBytes(data, 4) == 2);
CHECK(data == std::string("AB"));
}
THEN("peek() returns the first value") {
CHECK(stream.peek() == 'A');
CHECK(stream.peek() == 'A');
}
}
}

View File

@@ -1,337 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "FailingAllocator.hpp"
#include "StreamUtils/Clients/MemoryClient.hpp"
#include "StreamUtils/Clients/ReadBufferingClient.hpp"
#include "StreamUtils/Clients/SpyingClient.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("ReadBufferingClient") {
MemoryClient target(64);
StringPrint log;
SpyingClient spy{target, log};
SUBCASE("capacity = 4") {
ReadBufferingClient bufferedClient{spy, 4};
Client& client = bufferedClient;
SUBCASE("available()") {
target.print("ABCDEFGH");
SUBCASE("empty input") {
target.flush();
CHECK(client.available() == 0);
CHECK(log.str() == "available() -> 0");
}
SUBCASE("read empty input") {
target.flush();
client.read();
CHECK(client.available() == 0);
CHECK(log.str() ==
"available() -> 0"
"read() -> -1"
"available() -> 0");
}
SUBCASE("same a target") {
CHECK(client.available() == 8);
CHECK(log.str() == "available() -> 8");
}
SUBCASE("target + in buffer") {
client.read();
CHECK(client.available() == 7);
CHECK(log.str() ==
"available() -> 8"
"read(4) -> 4"
"available() -> 4");
}
}
SUBCASE("peek()") {
SUBCASE("returns -1 when empty") {
target.flush();
int result = client.peek();
CHECK(result == -1);
CHECK(log.str() == "peek() -> -1");
}
SUBCASE("doesn't call readBytes() when buffer is empty") {
target.print("A");
int result = client.peek();
CHECK(result == 'A');
CHECK(log.str() == "peek() -> 65");
}
SUBCASE("doesn't call peek() when buffer is full") {
target.print("AB");
client.read();
int result = client.peek();
CHECK(result == 'B');
CHECK(log.str() ==
"available() -> 2"
"read(2) -> 2");
}
}
SUBCASE("read()") {
SUBCASE("reads 4 bytes at a time") {
target.print("ABCDEFG");
std::string result;
for (int i = 0; i < 7; i++) {
result += (char)client.read();
}
CHECK(result == "ABCDEFG");
CHECK(log.str() ==
"available() -> 7"
"read(4) -> 4"
"available() -> 3"
"read(3) -> 3");
}
SUBCASE("returns -1 when empty") {
target.flush();
int result = client.read();
CHECK(result == -1);
CHECK(log.str() ==
"available() -> 0"
"read() -> -1");
}
}
SUBCASE("read()") {
SUBCASE("empty input") {
target.flush();
char c;
size_t result = client.readBytes(&c, 1);
CHECK(result == 0);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 0"
"readBytes(1) -> 0 [timeout]");
#else
CHECK(log.str() ==
"available() -> 0"
"read() -> -1"); // [timeout] from timedRead()
#endif
}
SUBCASE("reads 4 bytes when requested one") {
target.print("ABCDEFG");
char c;
size_t result = client.readBytes(&c, 1);
CHECK(c == 'A');
CHECK(result == 1);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 7"
"readBytes(4) -> 4");
#else
CHECK(log.str() ==
"available() -> 7"
"read(4) -> 4");
#endif
}
SUBCASE("copy one byte from buffer") {
target.print("ABCDEFGH");
client.read(); // load buffer
char c;
size_t result = client.readBytes(&c, 1);
CHECK(c == 'B');
CHECK(result == 1);
CHECK(log.str() ==
"available() -> 8"
"read(4) -> 4");
}
SUBCASE("copy content from buffer then bypass buffer") {
target.print("ABCDEFGH");
client.read(); // load buffer
char c[8] = {0};
size_t result = client.readBytes(c, 7);
CHECK(c == std::string("BCDEFGH"));
CHECK(result == 7);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 8"
"read(4) -> 4"
"available() -> 4"
"readBytes(4) -> 4");
#else
CHECK(log.str() ==
"available() -> 8"
"read(4) -> 4"
"available() -> 4"
"read(4) -> 4");
#endif
}
SUBCASE("copy content from buffer twice") {
target.print("ABCDEFGH");
client.read(); // load buffer
char c[8] = {0};
size_t result = client.readBytes(c, 4);
CHECK(c == std::string("BCDE"));
CHECK(result == 4);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 8"
"read(4) -> 4"
"available() -> 4"
"readBytes(4) -> 4");
#else
CHECK(log.str() ==
"available() -> 8"
"read(4) -> 4"
"available() -> 4"
"read(4) -> 4");
#endif
}
SUBCASE("read past the end") {
target.print("A");
char c;
client.readBytes(&c, 1);
size_t result = client.readBytes(&c, 1);
CHECK(result == 0);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 1"
"readBytes(1) -> 1"
"available() -> 0"
"readBytes(1) -> 0 [timeout]");
#else
CHECK(log.str() ==
"available() -> 1"
"read() -> 65"
"available() -> 0"
"read() -> -1"); // [timeout] from timedRead()
#endif
}
}
SUBCASE("flush()") {
client.flush();
CHECK(log.str() == "flush()");
}
SUBCASE("copy constructor") {
target.print("ABCDEFGH");
bufferedClient.read();
auto dup = bufferedClient;
int result = dup.read();
CHECK(result == 'B');
CHECK(log.str() ==
"available() -> 8"
"read(4) -> 4");
}
}
SUBCASE("No memory") {
BasicReadBufferingClient<FailingAllocator> client(spy, 4);
SUBCASE("available()") {
target.print("ABC");
CHECK(client.available() == 3);
}
// SUBCASE("capacity()") {
// CHECK(client.capacity() == 0);
// }
SUBCASE("peek()") {
target.print("ABC");
int c = client.peek();
CHECK(c == 'A');
CHECK(log.str() == "peek() -> 65");
}
SUBCASE("read()") {
target.print("ABC");
int c = client.read();
CHECK(c == 'A');
CHECK(log.str() == "read() -> 65");
}
SUBCASE("readBytes()") {
target.print("ABC");
char s[4] = {0};
int n = client.readBytes(s, 3);
CHECK(n == 3);
CHECK(s == std::string("ABC"));
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(3) -> 3");
#endif
}
}
SUBCASE("Real example") {
ReadBufferingClient bufferedClient{spy, 64};
Client& client = bufferedClient;
target.print("{\"helloWorld\":\"Hello World\"}");
char c[] = "ABCDEFGH";
CHECK(client.readBytes(&c[0], 1) == 1);
CHECK(client.readBytes(&c[1], 1) == 1);
CHECK(client.readBytes(&c[2], 1) == 1);
CHECK(client.readBytes(&c[3], 1) == 1);
CHECK(c == std::string("{\"heEFGH"));
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 28"
"readBytes(28) -> 28");
#else
CHECK(log.str() ==
"available() -> 28"
"read(28) -> 28");
#endif
}
}

View File

@@ -1,318 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "FailingAllocator.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "StreamUtils/Streams/ReadBufferingStream.hpp"
#include "StreamUtils/Streams/SpyingStream.hpp"
#include "StreamUtils/Streams/StringStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("ReadBufferingStream") {
StringStream upstream;
StringPrint log;
SpyingStream spy{upstream, log};
SUBCASE("capacity = 4") {
ReadBufferingStream bufferedStream{spy, 4};
Stream& stream = bufferedStream;
SUBCASE("available()") {
SUBCASE("empty input") {
CHECK(stream.available() == 0);
CHECK(log.str() == "available() -> 0");
}
SUBCASE("read empty input") {
int n = stream.read();
CHECK(n == -1);
CHECK(stream.available() == 0);
CHECK(log.str() ==
"available() -> 0"
"read() -> -1"
"available() -> 0");
}
SUBCASE("same a upstream") {
upstream.print("ABCDEFGH");
CHECK(stream.available() == 8);
CHECK(log.str() == "available() -> 8");
}
SUBCASE("upstream + in buffer") {
upstream.print("ABCDEFGH");
int n = stream.read();
CHECK(n == 'A');
CHECK(stream.available() == 7);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 8"
"readBytes(4) -> 4"
"available() -> 4");
#endif
}
}
SUBCASE("peek()") {
SUBCASE("returns -1 when empty") {
upstream.flush();
int result = stream.peek();
CHECK(result == -1);
CHECK(log.str() == "peek() -> -1");
}
SUBCASE("doesn't call readBytes() when buffer is empty") {
upstream.print("A");
int result = stream.peek();
CHECK(result == 'A');
CHECK(log.str() == "peek() -> 65");
}
SUBCASE("doesn't call peek() when buffer is full") {
upstream.print("AB");
stream.read();
int result = stream.peek();
CHECK(result == 'B');
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 2"
"readBytes(2) -> 2");
#endif
}
}
SUBCASE("read()") {
SUBCASE("reads 4 bytes at a time") {
upstream.print("ABCDEFG");
std::string result;
for (int i = 0; i < 7; i++) {
result += (char)stream.read();
}
CHECK(result == "ABCDEFG");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 7"
"readBytes(4) -> 4"
"available() -> 3"
"readBytes(3) -> 3");
#endif
}
SUBCASE("returns -1 when empty") {
upstream.flush();
int result = stream.read();
CHECK(result == -1);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 0"
"read() -> -1");
#endif
}
}
SUBCASE("readBytes()") {
SUBCASE("empty input") {
upstream.flush();
char c;
size_t result = stream.readBytes(&c, 1);
CHECK(result == 0);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 0"
"readBytes(1) -> 0 [timeout]");
#endif
}
SUBCASE("reads 4 bytes when requested one") {
upstream.print("ABCDEFG");
char c;
size_t result = stream.readBytes(&c, 1);
CHECK(c == 'A');
CHECK(result == 1);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 7"
"readBytes(4) -> 4");
#endif
}
SUBCASE("copy one byte from buffer") {
upstream.print("ABCDEFGH");
stream.read(); // load buffer
char c;
size_t result = stream.readBytes(&c, 1);
CHECK(c == 'B');
CHECK(result == 1);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 8"
"readBytes(4) -> 4");
#endif
}
SUBCASE("copy content from buffer then bypass buffer") {
upstream.print("ABCDEFGH");
stream.read(); // load buffer
char c[8] = {0};
size_t result = stream.readBytes(c, 7);
CHECK(c == std::string("BCDEFGH"));
CHECK(result == 7);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 8"
"readBytes(4) -> 4"
"available() -> 4"
"readBytes(4) -> 4");
#endif
}
SUBCASE("copy content from buffer twice") {
upstream.print("ABCDEFGH");
stream.read(); // load buffer
char c[8] = {0};
size_t result = stream.readBytes(c, 4);
CHECK(c == std::string("BCDE"));
CHECK(result == 4);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 8"
"readBytes(4) -> 4"
"available() -> 4"
"readBytes(4) -> 4");
#endif
}
SUBCASE("read past the end") {
upstream.print("A");
char c;
stream.readBytes(&c, 1);
size_t result = stream.readBytes(&c, 1);
CHECK(result == 0);
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 1"
"readBytes(1) -> 1"
"available() -> 0"
"readBytes(1) -> 0 [timeout]");
#endif
}
}
SUBCASE("flush()") {
stream.flush();
CHECK(log.str() == "flush()");
}
SUBCASE("copy constructor") {
upstream.print("ABCDEFGH");
bufferedStream.read();
auto dup = bufferedStream;
int result = dup.read();
CHECK(result == 'B');
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 8"
"readBytes(4) -> 4");
#endif
}
}
SUBCASE("No memory") {
BasicReadBufferingStream<FailingAllocator> stream(spy, 4);
SUBCASE("available()") {
upstream.print("ABC");
CHECK(stream.available() == 3);
}
// SUBCASE("capacity()") {
// CHECK(stream.capacity() == 0);
// }
SUBCASE("peek()") {
upstream.print("ABC");
int c = stream.peek();
CHECK(c == 'A');
CHECK(log.str() == "peek() -> 65");
}
SUBCASE("read()") {
upstream.print("ABC");
int c = stream.read();
CHECK(c == 'A');
CHECK(log.str() == "read() -> 65");
}
SUBCASE("readBytes()") {
upstream.print("ABC");
char s[4] = {0};
int n = stream.readBytes(s, 3);
CHECK(n == 3);
CHECK(s == std::string("ABC"));
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(3) -> 3");
#endif
}
}
SUBCASE("Real example") {
ReadBufferingStream bufferedStream{spy, 64};
Stream& stream = bufferedStream;
upstream.print("{\"helloWorld\":\"Hello World\"}");
char c[] = "ABCDEFGH";
CHECK(stream.readBytes(&c[0], 1) == 1);
CHECK(stream.readBytes(&c[1], 1) == 1);
CHECK(stream.readBytes(&c[2], 1) == 1);
CHECK(stream.readBytes(&c[3], 1) == 1);
CHECK(c == std::string("{\"heEFGH"));
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() ==
"available() -> 28"
"readBytes(28) -> 28");
#endif
}
}

View File

@@ -1,139 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "FailingAllocator.hpp"
#include "StreamUtils/Clients/MemoryClient.hpp"
#include "StreamUtils/Clients/ReadLoggingClient.hpp"
#include "StreamUtils/Clients/SpyingClient.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("ReadLoggingClient") {
MemoryClient target(4);
StringPrint log;
SpyingClient upstreamSpy{target, log};
StringPrint output;
ReadLoggingClient loggingClient{upstreamSpy, output};
SUBCASE("available()") {
target.print("ABC");
size_t n = loggingClient.available();
CHECK(n == 3);
CHECK(log.str() == "available() -> 3");
CHECK(output.str() == "");
}
SUBCASE("connect(IPAddress)") {
int n = loggingClient.connect(IPAddress("1.2.3.4"), 80);
CHECK(n == 1);
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
CHECK(output.str() == "");
}
SUBCASE("connect(const char*)") {
int n = loggingClient.connect("1.2.3.4", 80);
CHECK(n == 1);
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
CHECK(output.str() == "");
}
SUBCASE("connected()") {
uint8_t n = loggingClient.connected();
CHECK(n == false);
CHECK(log.str() == "connected() -> 0");
CHECK(output.str() == "");
}
SUBCASE("stop()") {
loggingClient.stop();
CHECK(log.str() == "stop()");
CHECK(output.str() == "");
}
SUBCASE("operator bool()") {
bool n = loggingClient.operator bool();
CHECK(n == true);
CHECK(log.str() == "operator bool() -> true");
CHECK(output.str() == "");
}
SUBCASE("peek()") {
target.print("ABC");
int n = loggingClient.peek();
CHECK(n == 'A');
CHECK(log.str() == "peek() -> 65");
CHECK(output.str() == "");
}
SUBCASE("read()") {
target.print("ABC");
int n = loggingClient.read();
CHECK(n == 'A');
CHECK(log.str() == "read() -> 65");
CHECK(output.str() == "A");
}
SUBCASE("read(uint8_t*,size_t)") {
target.print("ABC");
uint8_t s[4] = {0};
size_t n = loggingClient.read(s, 4);
CHECK(n == 3);
CHECK(log.str() == "read(4) -> 3 [timeout]");
CHECK(output.str() == "ABC");
}
SUBCASE("readBytes()") {
target.print("ABC");
char s[4] = {0};
size_t n = loggingClient.readBytes(s, 4);
CHECK(n == 3);
CHECK(output.str() == "ABC");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(4) -> 3 [timeout]");
#endif
}
SUBCASE("write(char)") {
int n = loggingClient.write('A');
CHECK(n == 1);
CHECK(log.str() == "write('A') -> 1");
CHECK(output.str() == "");
}
SUBCASE("write(char*,size_t)") {
int n = loggingClient.write("ABCDEF", 6);
CHECK(n == 4);
CHECK(log.str() == "write('ABCDEF', 6) -> 4");
CHECK(output.str() == "");
}
SUBCASE("flush()") {
loggingClient.flush();
CHECK(log.str() == "flush()");
}
}

View File

@@ -1,89 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "FailingAllocator.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "StreamUtils/Streams/MemoryStream.hpp"
#include "StreamUtils/Streams/ReadLoggingStream.hpp"
#include "StreamUtils/Streams/SpyingStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("ReadLoggingStream") {
MemoryStream upstream(4);
StringPrint log;
SpyingStream upstreamSpy{upstream, log};
StringPrint output;
ReadLoggingStream loggingStream{upstreamSpy, output};
SUBCASE("available()") {
upstream.print("ABC");
size_t n = loggingStream.available();
CHECK(n == 3);
CHECK(log.str() == "available() -> 3");
CHECK(output.str() == "");
}
SUBCASE("peek()") {
upstream.print("ABC");
int n = loggingStream.peek();
CHECK(n == 'A');
CHECK(log.str() == "peek() -> 65");
CHECK(output.str() == "");
}
SUBCASE("read()") {
upstream.print("ABC");
int n = loggingStream.read();
CHECK(n == 'A');
CHECK(log.str() == "read() -> 65");
CHECK(output.str() == "A");
}
SUBCASE("readBytes()") {
upstream.print("ABC");
char s[4] = {0};
size_t n = loggingStream.readBytes(s, 4);
CHECK(n == 3);
CHECK(output.str() == "ABC");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(4) -> 3 [timeout]");
#endif
}
SUBCASE("write(char)") {
int n = loggingStream.write('A');
CHECK(n == 1);
CHECK(log.str() == "write('A') -> 1");
CHECK(output.str() == "");
}
SUBCASE("write(char*,size_t)") {
int n = loggingStream.write("ABCDEF", 6);
CHECK(n == 4);
CHECK(log.str() == "write('ABCDEF', 6) -> 4");
CHECK(output.str() == "");
}
SUBCASE("flush()") {
loggingStream.flush();
CHECK(log.str() == "flush()");
}
}

View File

@@ -1,89 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "FailingAllocator.hpp"
#include "StreamUtils/Streams/ReadThrottlingStream.hpp"
#include "StreamUtils/Streams/StringStream.hpp"
#include "doctest.h"
#include <sstream>
using namespace StreamUtils;
class SpyingThrottler {
public:
SpyingThrottler(uint32_t rate) {
_log << "C(" << rate << ")";
}
SpyingThrottler(const SpyingThrottler& src) {
_log << src._log.str();
}
void throttle() {
_log << "T";
}
std::string log() const {
return _log.str();
}
private:
std::stringstream _log;
};
using ReadThrottlingStream = BasicReadThrottlingStream<SpyingThrottler>;
TEST_CASE("ReadThrottlingStream") {
StringStream upstream;
ReadThrottlingStream throttledStream{upstream, 4};
Stream& stream = throttledStream;
const SpyingThrottler& throttler = throttledStream.throttler();
SUBCASE("available()") {
upstream.print("ABCD");
CHECK(stream.available() == 4);
CHECK(throttler.log() == "C(4)");
}
SUBCASE("read()") {
upstream.print("ABCD");
int n = stream.read();
CHECK(n == 'A');
CHECK(throttler.log() == "C(4)T");
}
SUBCASE("readBytes()") {
upstream.print("ABCD");
char output[8] = {0};
SUBCASE("read more than available") {
size_t n = stream.readBytes(output, sizeof(output));
CHECK(n == 4);
CHECK(strcmp("ABCD", output) == 0);
CHECK(throttler.log() == "C(4)TTTTT");
}
SUBCASE("read less than available") {
size_t n = stream.readBytes(output, 2);
CHECK(n == 2);
CHECK(strcmp("AB", output) == 0);
CHECK(throttler.log() == "C(4)TT");
}
SUBCASE("read as many as available") {
size_t n = stream.readBytes(output, 4);
CHECK(n == 4);
CHECK(strcmp("ABCD", output) == 0);
CHECK(throttler.log() == "C(4)TTTT");
}
}
}

View File

@@ -1,36 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <Arduino.h>
#include "StreamUtils/Ports/DefaultAllocator.hpp"
class SpyingAllocator {
public:
SpyingAllocator(Print& log) : _log(&log) {}
bool forceFail = false;
void* allocate(size_t n) {
void* ptr = forceFail ? 0 : _allocator.allocate(n);
_log->print("allocate(");
_log->print(n);
_log->print(") -> ");
_log->print(ptr ? "ptr" : "null");
return ptr;
}
void deallocate(void* ptr) {
_log->print("deallocate(");
_log->print(ptr ? "ptr" : "null");
_log->print(")");
_allocator.deallocate(ptr);
}
private:
Print* _log;
StreamUtils::DefaultAllocator _allocator;
};

View File

@@ -1,77 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "StreamUtils/Prints/StringPrint.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("StringPrint") {
WHEN("Constructed with no argument") {
StringPrint s;
THEN("str() return an empty String") {
CHECK(s.str() == "");
}
THEN("write(uint8_t) appends the string") {
s.write('A');
s.write('B');
CHECK(s.str() == "AB");
}
THEN("write(uint8_t) return 1") {
CHECK(s.write('A') == 1);
CHECK(s.write('B') == 1);
}
THEN("write(0) return 0") {
CHECK(s.write(0) == 0);
}
THEN("write(uint8_t*, size_t) appends the string") {
s.write(reinterpret_cast<const uint8_t*>("ABXXX"), 2);
s.write(reinterpret_cast<const uint8_t*>("CDEXX"), 3);
CHECK(s.str() == "ABCDE");
}
THEN("write(uint8_t*, size_t) return number of chars written") {
uint8_t dummy[32] = {1, 2, 3, 0, 5, 6};
CHECK(s.write(dummy, 2) == 2);
CHECK(s.write(dummy, 3) == 3);
CHECK(s.write(dummy, 4) == 3);
}
THEN("str(String) sets the string") {
s.str("world!");
CHECK(s.str() == "world!");
}
}
WHEN("Constructed with string") {
StringPrint s("hello");
THEN("str() return the stirng passed to contructor") {
CHECK(s.str() == "hello");
}
THEN("write(uint8_t) appends the string") {
s.write('A');
s.write('B');
CHECK(s.str() == "helloAB");
}
THEN("write(uint8_t*, size_t) appends the string") {
s.write(reinterpret_cast<const uint8_t*>("ABXXX"), 2);
s.write(reinterpret_cast<const uint8_t*>("CDEXX"), 3);
CHECK(s.str() == "helloABCDE");
}
THEN("str(String) replaces the string") {
s.str("world!");
CHECK(s.str() == "world!");
}
}
}

View File

@@ -1,116 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "StreamUtils/Streams/StringStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("StringStream") {
WHEN("Constructed with no argument") {
StringStream s;
THEN("str() return an empty String") {
CHECK(s.str() == "");
}
THEN("write(uint8_t) appends the string") {
s.write('A');
s.write('B');
CHECK(s.str() == "AB");
}
THEN("write(uint8_t) return 1") {
CHECK(s.write('A') == 1);
CHECK(s.write('B') == 1);
}
THEN("write(0) return 0") {
CHECK(s.write(0) == 0);
}
THEN("write(uint8_t*, size_t) appends the string") {
s.write(reinterpret_cast<const uint8_t*>("ABXXX"), 2);
s.write(reinterpret_cast<const uint8_t*>("CDEXX"), 3);
CHECK(s.str() == "ABCDE");
}
THEN("write(uint8_t*, size_t) return number of chars written") {
uint8_t dummy[32] = {1, 2, 3, 0, 5, 6};
CHECK(s.write(dummy, 2) == 2);
CHECK(s.write(dummy, 3) == 3);
CHECK(s.write(dummy, 4) == 3);
}
THEN("str(String) sets the string") {
s.str("world!");
CHECK(s.str() == "world!");
}
THEN("available() returns 0") {
CHECK(s.available() == 0);
}
THEN("peek() return -1") {
CHECK(s.peek() == -1);
}
THEN("peek() return -1") {
CHECK(s.read() == -1);
}
}
WHEN("Constructed with string") {
StringStream s("hello");
THEN("str() returns the string passed to contructor") {
CHECK(s.str() == "hello");
}
THEN("available() returns the length passed to the constructor") {
CHECK(s.available() == 5);
}
THEN("write(uint8_t) appends the string") {
s.write('A');
s.write('B');
CHECK(s.str() == "helloAB");
}
THEN("write(uint8_t*, size_t) appends the string") {
s.write(reinterpret_cast<const uint8_t*>("ABXXX"), 2);
s.write(reinterpret_cast<const uint8_t*>("CDEXX"), 3);
CHECK(s.str() == "helloABCDE");
}
THEN("str(String) replaces the string") {
s.str("world!");
CHECK(s.str() == "world!");
}
THEN("peek() return the first char") {
CHECK(s.peek() == 'h');
}
THEN("peek() return the next char") {
CHECK(s.read() == 'h');
CHECK(s.read() == 'e');
}
THEN("readBytes() can return the begining of the string") {
char buffer[32] = {0};
CHECK(s.readBytes(buffer, 3) == 3);
CHECK(buffer == std::string("hel"));
CHECK(s.available() == 2);
}
THEN("readBytes() can return the whole string") {
char buffer[32] = {0};
CHECK(s.readBytes(buffer, 32) == 5);
CHECK(buffer == std::string("hello"));
CHECK(s.available() == 0);
}
}
}

View File

@@ -1,104 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "FailingAllocator.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "StreamUtils/Prints/WaitingPrint.hpp"
#include "StreamUtils/Streams/MemoryStream.hpp"
#include "StreamUtils/Streams/SpyingStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("WaitingPrint") {
MemoryStream upstream(4);
StringPrint log;
SpyingStream spy{upstream, log};
WaitingPrint stream{static_cast<Print&>(spy), [&spy]() { spy.flush(); }};
SUBCASE("write(char*, size_t)") {
SUBCASE("no need to wait") {
CHECK(stream.print("ABC") == 3);
CHECK(log.str() == "write('ABC', 3) -> 3");
}
SUBCASE("need to wait") {
CHECK(stream.print("ABCDEFG") == 7);
CHECK(log.str() ==
"write('ABCDEFG', 7) -> 4"
"flush()"
"write('EFG', 3) -> 3");
}
SUBCASE("need to wait twice") {
CHECK(stream.print("ABCDEFGIJKL") == 11);
CHECK(log.str() ==
"write('ABCDEFGIJKL', 11) -> 4"
"flush()"
"write('EFGIJKL', 7) -> 4"
"flush()"
"write('JKL', 3) -> 3");
}
SUBCASE("doesn't wait when timeout is 0") {
stream.setTimeout(0);
CHECK(stream.print("ABCDEFG") == 4);
CHECK(log.str() == "write('ABCDEFG', 7) -> 4");
}
}
SUBCASE("write(char)") {
SUBCASE("no need to wait") {
CHECK(stream.write('A') == 1);
CHECK(stream.write('B') == 1);
CHECK(stream.write('C') == 1);
CHECK(log.str() ==
"write('A') -> 1"
"write('B') -> 1"
"write('C') -> 1");
}
SUBCASE("need to wait") {
for (int i = 0; i < 7; i++)
CHECK(stream.write("ABCDEFG"[i]) == 1);
CHECK(log.str() ==
"write('A') -> 1"
"write('B') -> 1"
"write('C') -> 1"
"write('D') -> 1"
"write('E') -> 0"
"flush()"
"write('E') -> 1"
"write('F') -> 1"
"write('G') -> 1");
}
SUBCASE("doesn't wait when timeout is 0") {
stream.setTimeout(0);
CHECK(stream.write('A') == 1);
CHECK(stream.write('B') == 1);
CHECK(stream.write('C') == 1);
CHECK(stream.write('D') == 1);
CHECK(stream.write('E') == 0);
CHECK(log.str() ==
"write('A') -> 1"
"write('B') -> 1"
"write('C') -> 1"
"write('D') -> 1"
"write('E') -> 0");
}
}
}

View File

@@ -1,203 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "FailingAllocator.hpp"
#include "StreamUtils/Clients/MemoryClient.hpp"
#include "StreamUtils/Clients/SpyingClient.hpp"
#include "StreamUtils/Clients/WriteBufferingClient.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("WriteBufferingClient") {
MemoryClient target(64);
StringPrint log;
SpyingClient spy{target, log};
GIVEN("capacity is 4") {
WriteBufferingClient bufferingClient{spy, 4};
SUBCASE("available()") {
target.print("ABC");
CHECK(bufferingClient.available() == 3);
CHECK(log.str() == "available() -> 3");
}
SUBCASE("connect(IPAddress)") {
int n = bufferingClient.connect(IPAddress("1.2.3.4"), 80);
CHECK(n == 1);
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
}
SUBCASE("connect(const char*)") {
int n = bufferingClient.connect("1.2.3.4", 80);
CHECK(n == 1);
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
}
SUBCASE("connected()") {
uint8_t n = bufferingClient.connected();
CHECK(n == false);
CHECK(log.str() == "connected() -> 0");
}
SUBCASE("stop()") {
bufferingClient.write("ABC", 3);
bufferingClient.stop();
CHECK(log.str() ==
"write('ABC', 3) -> 3"
"stop()");
}
SUBCASE("operator bool()") {
bool n = bufferingClient.operator bool();
CHECK(n == true);
CHECK(log.str() == "operator bool() -> true");
}
SUBCASE("flush() forwards to target)") {
bufferingClient.flush();
CHECK(log.str() == "flush()");
}
SUBCASE("flush() calls write() and flush()") {
bufferingClient.write("ABC", 3);
bufferingClient.flush();
CHECK(log.str() ==
"write('ABC', 3) -> 3"
"flush()");
}
SUBCASE("peek()") {
target.print("ABC");
CHECK(bufferingClient.peek() == 'A');
CHECK(log.str() == "peek() -> 65");
}
SUBCASE("read()") {
target.print("ABC");
CHECK(bufferingClient.read() == 'A');
CHECK(log.str() == "read() -> 65");
}
SUBCASE("readBytes()") {
target.print("ABC");
char s[4] = {0};
int n = bufferingClient.readBytes(s, 3);
CHECK(n == 3);
CHECK(s == std::string("ABC"));
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(3) -> 3");
#endif
}
GIVEN("the buffer is empty") {
SUBCASE("write(uint8_t)") {
int n = bufferingClient.write('A');
CHECK(n == 1);
CHECK(log.str() == "");
}
SUBCASE("write(uint8_t) should flush") {
bufferingClient.write('A');
bufferingClient.write('B');
bufferingClient.write('C');
bufferingClient.write('D');
bufferingClient.write('E');
CHECK(log.str() == "write('ABCD', 4) -> 4");
}
SUBCASE("write(char*,3) goes in buffer") {
size_t n = bufferingClient.write("ABC", 3);
CHECK(n == 3);
CHECK(log.str() == "");
}
SUBCASE("write(char*,4) bypasses buffer") {
size_t n = bufferingClient.write("ABCD", 4);
CHECK(n == 4);
CHECK(log.str() == "write('ABCD', 4) -> 4");
}
SUBCASE("write(char*,2) bypasses buffer") {
size_t n = bufferingClient.write("ABCD", 4);
CHECK(n == 4);
CHECK(log.str() == "write('ABCD', 4) -> 4");
}
}
GIVEN("one byte in the buffer") {
bufferingClient.write('A');
SUBCASE("write(char*,3) goes in buffer and flush") {
size_t n = bufferingClient.write("BCD", 3);
CHECK(n == 3);
CHECK(log.str() == "write('ABCD', 4) -> 4");
}
SUBCASE("write(char*,7) bypasses") {
size_t n = bufferingClient.write("BCDEFGH", 7);
CHECK(n == 7);
CHECK(log.str() ==
"write('ABCD', 4) -> 4"
"write('EFGH', 4) -> 4");
}
}
}
GIVEN("capacity is 0") {
WriteBufferingClient bufferingClient{spy, 0};
SUBCASE("write(uint8_t) forwards to target") {
int n = bufferingClient.write('X');
CHECK(n == 1);
CHECK(log.str() == "write('X') -> 1");
}
SUBCASE("write(char*,1) forwards to target") {
int n = bufferingClient.write("A", 1);
CHECK(n == 1);
CHECK(log.str() == "write('A', 1) -> 1");
}
SUBCASE("flush() forwards to target") {
bufferingClient.flush();
CHECK(log.str() == "flush()");
}
}
SUBCASE("Destructor should flush") {
{
WriteBufferingClient bufferingClient{spy, 10};
bufferingClient.write("ABC", 3);
}
CHECK(log.str() == "write('ABC', 3) -> 3");
}
}

View File

@@ -1,166 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "FailingAllocator.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "StreamUtils/Streams/MemoryStream.hpp"
#include "StreamUtils/Streams/SpyingStream.hpp"
#include "StreamUtils/Streams/WriteBufferingStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("WriteBufferingStream") {
MemoryStream upstream(64);
StringPrint log;
SpyingStream spy{upstream, log};
GIVEN("capacity is 4") {
WriteBufferingStream stream{spy, 4};
SUBCASE("available()") {
upstream.print("ABC");
CHECK(stream.available() == 3);
CHECK(log.str() == "available() -> 3");
}
SUBCASE("flush() forwards to upstream)") {
stream.flush();
CHECK(log.str() == "flush()");
}
SUBCASE("flush() calls write() and flush()") {
stream.write("ABC", 3);
stream.flush();
CHECK(log.str() ==
"write('ABC', 3) -> 3"
"flush()");
}
SUBCASE("peek()") {
upstream.print("ABC");
CHECK(stream.peek() == 'A');
CHECK(log.str() == "peek() -> 65");
}
SUBCASE("read()") {
upstream.print("ABC");
CHECK(stream.read() == 'A');
CHECK(log.str() == "read() -> 65");
}
SUBCASE("readBytes()") {
upstream.print("ABC");
char s[4] = {0};
int n = stream.readBytes(s, 3);
CHECK(n == 3);
CHECK(s == std::string("ABC"));
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(3) -> 3");
#endif
}
GIVEN("the buffer is empty") {
SUBCASE("write(uint8_t)") {
int n = stream.write('A');
CHECK(n == 1);
CHECK(log.str() == "");
}
SUBCASE("write(uint8_t) should flush") {
stream.write('A');
stream.write('B');
stream.write('C');
stream.write('D');
stream.write('E');
CHECK(log.str() == "write('ABCD', 4) -> 4");
}
SUBCASE("write(char*,3) goes in buffer") {
size_t n = stream.write("ABC", 3);
CHECK(n == 3);
CHECK(log.str() == "");
}
SUBCASE("write(char*,4) bypasses buffer") {
size_t n = stream.write("ABCD", 4);
CHECK(n == 4);
CHECK(log.str() == "write('ABCD', 4) -> 4");
}
SUBCASE("write(char*,2) bypasses buffer") {
size_t n = stream.write("ABCD", 4);
CHECK(n == 4);
CHECK(log.str() == "write('ABCD', 4) -> 4");
}
}
GIVEN("one byte in the buffer") {
stream.write('A');
SUBCASE("write(char*,3) goes in buffer and flush") {
size_t n = stream.write("BCD", 3);
CHECK(n == 3);
CHECK(log.str() == "write('ABCD', 4) -> 4");
}
SUBCASE("write(char*,7) bypasses") {
size_t n = stream.write("BCDEFGH", 7);
CHECK(n == 7);
CHECK(log.str() ==
"write('ABCD', 4) -> 4"
"write('EFGH', 4) -> 4");
}
}
}
GIVEN("capacity is 0") {
WriteBufferingStream stream{spy, 0};
SUBCASE("write(uint8_t) forwards to upstream") {
int n = stream.write('X');
CHECK(n == 1);
CHECK(log.str() == "write('X') -> 1");
}
SUBCASE("write(char*,1) forwards to upstream") {
int n = stream.write("A", 1);
CHECK(n == 1);
CHECK(log.str() == "write('A', 1) -> 1");
}
SUBCASE("flush() forwards to upstream") {
stream.flush();
CHECK(log.str() == "flush()");
}
}
SUBCASE("Destructor should flush") {
{
WriteBufferingStream stream{spy, 10};
stream.write("ABC", 3);
}
CHECK(log.str() == "write('ABC', 3) -> 3");
}
}

View File

@@ -1,140 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "FailingAllocator.hpp"
#include "StreamUtils/Clients/MemoryClient.hpp"
#include "StreamUtils/Clients/SpyingClient.hpp"
#include "StreamUtils/Clients/WriteLoggingClient.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("WriteLoggingClient") {
MemoryClient target(4);
StringPrint log;
SpyingClient spy{target, log};
StringPrint output;
WriteLoggingClient loggingClient{spy, output};
SUBCASE("available()") {
target.print("ABC");
size_t n = loggingClient.available();
CHECK(n == 3);
CHECK(log.str() == "available() -> 3");
CHECK(output.str() == "");
}
SUBCASE("connect(IPAddress)") {
int n = loggingClient.connect(IPAddress("1.2.3.4"), 80);
CHECK(n == 1);
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
CHECK(output.str() == "");
}
SUBCASE("connect(const char*)") {
int n = loggingClient.connect("1.2.3.4", 80);
CHECK(n == 1);
CHECK(log.str() == "connect('1.2.3.4', 80) -> 1");
CHECK(output.str() == "");
}
SUBCASE("connected()") {
uint8_t n = loggingClient.connected();
CHECK(n == false);
CHECK(log.str() == "connected() -> 0");
CHECK(output.str() == "");
}
SUBCASE("stop()") {
loggingClient.stop();
CHECK(log.str() == "stop()");
CHECK(output.str() == "");
}
SUBCASE("operator bool()") {
bool n = loggingClient.operator bool();
CHECK(n == true);
CHECK(log.str() == "operator bool() -> true");
CHECK(output.str() == "");
}
SUBCASE("peek()") {
target.print("ABC");
int n = loggingClient.peek();
CHECK(n == 'A');
CHECK(log.str() == "peek() -> 65");
CHECK(output.str() == "");
}
SUBCASE("read()") {
target.print("ABC");
int n = loggingClient.read();
CHECK(n == 'A');
CHECK(log.str() == "read() -> 65");
CHECK(output.str() == "");
}
SUBCASE("read(uint8_t*,size_t)") {
target.print("ABC");
uint8_t s[4] = {0};
size_t n = loggingClient.read(s, 4);
CHECK(n == 3);
CHECK(log.str() == "read(4) -> 3 [timeout]");
CHECK(output.str() == "");
}
SUBCASE("readBytes()") {
target.print("ABC");
char s[4] = {0};
size_t n = loggingClient.readBytes(s, 4);
CHECK(n == 3);
CHECK(output.str() == "");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(4) -> 3 [timeout]");
#endif
}
SUBCASE("write(char)") {
int n = loggingClient.write('A');
CHECK(n == 1);
CHECK(log.str() == "write('A') -> 1");
CHECK(output.str() == "A");
}
SUBCASE("write(char*,size_t)") {
int n = loggingClient.write("ABCDEF", 6);
CHECK(n == 4);
CHECK(log.str() == "write('ABCDEF', 6) -> 4");
CHECK(output.str() == "ABCD");
}
SUBCASE("flush()") {
loggingClient.flush();
CHECK(output.str() == "");
CHECK(log.str() == "flush()");
}
}

View File

@@ -1,90 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "FailingAllocator.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "StreamUtils/Streams/MemoryStream.hpp"
#include "StreamUtils/Streams/SpyingStream.hpp"
#include "StreamUtils/Streams/WriteLoggingStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("WriteLoggingStream") {
MemoryStream upstream(4);
StringPrint log;
SpyingStream upstreamSpy{upstream, log};
StringPrint output;
WriteLoggingStream loggingStream{upstreamSpy, output};
SUBCASE("available()") {
upstream.print("ABC");
size_t n = loggingStream.available();
CHECK(n == 3);
CHECK(log.str() == "available() -> 3");
CHECK(output.str() == "");
}
SUBCASE("peek()") {
upstream.print("ABC");
int n = loggingStream.peek();
CHECK(n == 'A');
CHECK(log.str() == "peek() -> 65");
CHECK(output.str() == "");
}
SUBCASE("read()") {
upstream.print("ABC");
int n = loggingStream.read();
CHECK(n == 'A');
CHECK(log.str() == "read() -> 65");
CHECK(output.str() == "");
}
SUBCASE("readBytes()") {
upstream.print("ABC");
char s[4] = {0};
size_t n = loggingStream.readBytes(s, 4);
CHECK(n == 3);
CHECK(output.str() == "");
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
CHECK(log.str() == "readBytes(4) -> 3 [timeout]");
#endif
}
SUBCASE("write(char)") {
int n = loggingStream.write('A');
CHECK(n == 1);
CHECK(log.str() == "write('A') -> 1");
CHECK(output.str() == "A");
}
SUBCASE("write(char*,size_t)") {
int n = loggingStream.write("ABCDEF", 6);
CHECK(n == 4);
CHECK(log.str() == "write('ABCDEF', 6) -> 4");
CHECK(output.str() == "ABCD");
}
SUBCASE("flush()") {
loggingStream.flush();
CHECK(log.str() == "flush()");
CHECK(output.str() == "");
}
}

View File

@@ -1,104 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "FailingAllocator.hpp"
#include "StreamUtils/Clients/MemoryClient.hpp"
#include "StreamUtils/Clients/SpyingClient.hpp"
#include "StreamUtils/Clients/WriteWaitingClient.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("WriteWaitingClient") {
MemoryClient upstream(4);
StringPrint log;
SpyingClient spy{upstream, log};
WriteWaitingClient client{spy, [&spy]() { spy.flush(); }};
SUBCASE("write(char*, size_t)") {
SUBCASE("no need to wait") {
CHECK(client.print("ABC") == 3);
CHECK(log.str() == "write('ABC', 3) -> 3");
}
SUBCASE("need to wait") {
CHECK(client.print("ABCDEFG") == 7);
CHECK(log.str() ==
"write('ABCDEFG', 7) -> 4"
"flush()"
"write('EFG', 3) -> 3");
}
SUBCASE("need to wait twice") {
CHECK(client.print("ABCDEFGIJKL") == 11);
CHECK(log.str() ==
"write('ABCDEFGIJKL', 11) -> 4"
"flush()"
"write('EFGIJKL', 7) -> 4"
"flush()"
"write('JKL', 3) -> 3");
}
SUBCASE("doesn't wait when timeout is 0") {
client.setTimeout(0);
CHECK(client.print("ABCDEFG") == 4);
CHECK(log.str() == "write('ABCDEFG', 7) -> 4");
}
}
SUBCASE("write(char)") {
SUBCASE("no need to wait") {
CHECK(client.write('A') == 1);
CHECK(client.write('B') == 1);
CHECK(client.write('C') == 1);
CHECK(log.str() ==
"write('A') -> 1"
"write('B') -> 1"
"write('C') -> 1");
}
SUBCASE("need to wait") {
for (int i = 0; i < 7; i++)
CHECK(client.write("ABCDEFG"[i]) == 1);
CHECK(log.str() ==
"write('A') -> 1"
"write('B') -> 1"
"write('C') -> 1"
"write('D') -> 1"
"write('E') -> 0"
"flush()"
"write('E') -> 1"
"write('F') -> 1"
"write('G') -> 1");
}
SUBCASE("doesn't wait when timeout is 0") {
client.setTimeout(0);
CHECK(client.write('A') == 1);
CHECK(client.write('B') == 1);
CHECK(client.write('C') == 1);
CHECK(client.write('D') == 1);
CHECK(client.write('E') == 0);
CHECK(log.str() ==
"write('A') -> 1"
"write('B') -> 1"
"write('C') -> 1"
"write('D') -> 1"
"write('E') -> 0");
}
}
}

View File

@@ -1,104 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "FailingAllocator.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "StreamUtils/Streams/MemoryStream.hpp"
#include "StreamUtils/Streams/SpyingStream.hpp"
#include "StreamUtils/Streams/WriteWaitingStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("WriteWaitingStream") {
MemoryStream upstream(4);
StringPrint log;
SpyingStream spy{upstream, log};
WriteWaitingStream stream{spy, [&spy]() { spy.flush(); }};
SUBCASE("write(char*, size_t)") {
SUBCASE("no need to wait") {
CHECK(stream.print("ABC") == 3);
CHECK(log.str() == "write('ABC', 3) -> 3");
}
SUBCASE("need to wait") {
CHECK(stream.print("ABCDEFG") == 7);
CHECK(log.str() ==
"write('ABCDEFG', 7) -> 4"
"flush()"
"write('EFG', 3) -> 3");
}
SUBCASE("need to wait twice") {
CHECK(stream.print("ABCDEFGIJKL") == 11);
CHECK(log.str() ==
"write('ABCDEFGIJKL', 11) -> 4"
"flush()"
"write('EFGIJKL', 7) -> 4"
"flush()"
"write('JKL', 3) -> 3");
}
SUBCASE("doesn't wait when timeout is 0") {
stream.setTimeout(0);
CHECK(stream.print("ABCDEFG") == 4);
CHECK(log.str() == "write('ABCDEFG', 7) -> 4");
}
}
SUBCASE("write(char)") {
SUBCASE("no need to wait") {
CHECK(stream.write('A') == 1);
CHECK(stream.write('B') == 1);
CHECK(stream.write('C') == 1);
CHECK(log.str() ==
"write('A') -> 1"
"write('B') -> 1"
"write('C') -> 1");
}
SUBCASE("need to wait") {
for (int i = 0; i < 7; i++)
CHECK(stream.write("ABCDEFG"[i]) == 1);
CHECK(log.str() ==
"write('A') -> 1"
"write('B') -> 1"
"write('C') -> 1"
"write('D') -> 1"
"write('E') -> 0"
"flush()"
"write('E') -> 1"
"write('F') -> 1"
"write('G') -> 1");
}
SUBCASE("doesn't wait when timeout is 0") {
stream.setTimeout(0);
CHECK(stream.write('A') == 1);
CHECK(stream.write('B') == 1);
CHECK(stream.write('C') == 1);
CHECK(stream.write('D') == 1);
CHECK(stream.write('E') == 0);
CHECK(log.str() ==
"write('A') -> 1"
"write('B') -> 1"
"write('C') -> 1"
"write('D') -> 1"
"write('E') -> 0");
}
}
}

View File

@@ -1,18 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <Client.h>
#include <Print.h>
#include <Stream.h>
#include <WString.h>
#include <time.h>
inline unsigned long millis() {
return static_cast<unsigned long>(time(NULL));
}
inline void yield() {}

View File

@@ -1,22 +0,0 @@
# StreamUtils - github.com/bblanchon/ArduinoStreamUtils
# Copyright Benoit Blanchon 2019-2021
# MIT License
add_library(AvrCore
Client.h
EEPROM.cpp
EEPROM.h
Print.h
Stream.h
WString.h
)
target_include_directories(AvrCore
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
target_compile_definitions(AvrCore
PUBLIC
ARDUINO_ARCH_AVR
)

View File

@@ -1,27 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include "Stream.h"
#include "WString.h"
using IPAddress = String;
struct Client : Stream {
virtual int connect(IPAddress ip, uint16_t port) = 0;
virtual int connect(const char *host, uint16_t port) = 0;
virtual uint8_t connected() = 0;
virtual void stop() = 0;
virtual operator bool() = 0;
// Already in Stream
virtual size_t write(uint8_t) = 0;
virtual size_t write(const uint8_t *buf, size_t size) = 0;
virtual int available() = 0;
virtual int read() = 0;
// Curiously not in Stream
virtual int read(uint8_t *buf, size_t size) = 0;
};

View File

@@ -1,12 +0,0 @@
#include "EEPROM.h"
EEPROMClass EEPROM;
static uint8_t data[512];
uint8_t EEPROMClass::read(int address) {
return data[address];
}
void EEPROMClass::update(int address, uint8_t value) {
data[address] = value;
}

View File

@@ -1,12 +0,0 @@
#pragma once
#include <stdint.h>
class EEPROMClass {
public:
uint8_t read(int);
void update(int, uint8_t);
// void write(int, uint8_t); <- it exists but we want to use update() instead
};
extern EEPROMClass EEPROM;

View File

@@ -1,42 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <stdint.h>
#include <cstring>
#include <WString.h>
struct Print {
virtual size_t write(const uint8_t *buffer, size_t size) = 0;
virtual size_t write(uint8_t data) = 0;
virtual void flush() {}
size_t write(const char *buffer, size_t size) {
return write((const uint8_t *)buffer, size);
}
size_t print(const String &s) {
return write(s.c_str(), s.length());
}
size_t print(const char *s) {
return write(s, std::strlen(s));
}
size_t println() {
return 0;
}
template <typename T>
size_t print(const T &value) {
return print(String(value));
}
template <typename T>
size_t println(const T &value) {
return print(value);
}
};

View File

@@ -1,41 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include "Print.h"
struct Stream : Print {
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
size_t readBytes(char *buffer, size_t length) {
size_t count = 0;
while (count < length) {
int c = timedRead();
if (c < 0)
break;
*buffer++ = (char)c;
count++;
}
return count;
}
String readString() {
String result;
int c;
while ((c = timedRead()) >= 0) {
result += static_cast<char>(c);
}
return result;
}
void setTimeout(unsigned long) {}
protected:
int timedRead() {
return read();
}
};

View File

@@ -1,43 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <string>
class String : private std::string {
public:
String() {}
String(const String& s) : std::string(s) {}
String(String&& s) : std::string(std::move(s)) {}
String(const char* s) : std::string(s) {}
String(int n) : std::string(std::to_string(n)) {}
String& operator=(const String& rhs) {
std::string::operator=(rhs);
return *this;
}
using std::string::c_str;
using std::string::length;
using std::string::operator+=;
using std::string::operator[];
void remove(unsigned int index, unsigned int count) {
erase(begin() + index, begin() + index + count);
}
void toCharArray(char* buf, unsigned int bufsize,
unsigned int index = 0) const {
copy(buf, bufsize, index);
}
friend bool operator==(const String& lhs, const char* rhs) {
return static_cast<const std::string&>(lhs) == rhs;
}
friend std::ostream& operator<<(std::ostream& lhs, const String& rhs) {
return lhs << static_cast<const std::string&>(rhs);
}
};

View File

@@ -1,18 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <Client.h>
#include <Print.h>
#include <Stream.h>
#include <WString.h>
#include <time.h>
inline unsigned long millis() {
return static_cast<unsigned long>(time(NULL));
}
inline void yield() {}

View File

@@ -1,22 +0,0 @@
# StreamUtils - github.com/bblanchon/ArduinoStreamUtils
# Copyright Benoit Blanchon 2019-2021
# MIT License
add_library(Esp32Core
Client.h
EEPROM.cpp
EEPROM.h
Print.h
Stream.h
WString.h
)
target_include_directories(Esp32Core
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
target_compile_definitions(Esp32Core
PUBLIC
ARDUINO_ARCH_ESP32
)

View File

@@ -1,26 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include "Stream.h"
#include "WString.h"
using IPAddress = String;
class Client : public Stream {
public:
virtual int connect(IPAddress ip, uint16_t port) = 0;
virtual int connect(const char *host, uint16_t port) = 0;
virtual size_t write(uint8_t) = 0;
virtual size_t write(const uint8_t *buf, size_t size) = 0;
virtual int available() = 0;
virtual int read() = 0;
virtual int read(uint8_t *buf, size_t size) = 0;
virtual int peek() = 0;
virtual void flush() = 0;
virtual void stop() = 0;
virtual uint8_t connected() = 0;
virtual operator bool() = 0;
};

View File

@@ -1,20 +0,0 @@
#include "EEPROM.h"
#include <string.h> // memcpy
EEPROMClass EEPROM;
static uint8_t commitedData[512];
static uint8_t pendingData[512];
uint8_t EEPROMClass::read(int address) {
return commitedData[address];
}
void EEPROMClass::write(int address, uint8_t value) {
pendingData[address] = value;
}
bool EEPROMClass::commit() {
memcpy(commitedData, pendingData, 512);
return true;
}

View File

@@ -1,12 +0,0 @@
#pragma once
#include <stdint.h>
class EEPROMClass {
public:
uint8_t read(int);
void write(int, uint8_t);
bool commit();
};
extern EEPROMClass EEPROM;

View File

@@ -1,42 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <WString.h>
#include <stdint.h>
#include <cstring>
struct Print {
virtual ~Print() {}
virtual size_t write(const uint8_t *buffer, size_t size) = 0;
virtual size_t write(uint8_t data) = 0;
size_t write(const char *buffer, size_t size) {
return write((const uint8_t *)buffer, size);
}
size_t print(const String &s) {
return write(s.c_str(), s.length());
}
size_t print(const char *s) {
return write(s, std::strlen(s));
}
size_t println() {
return 0;
}
template <typename T>
size_t print(const T &value) {
return print(String(value));
}
template <typename T>
size_t println(const T &value) {
return print(value);
}
};

View File

@@ -1,48 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include "Print.h"
struct Stream : Print {
virtual ~Stream() {}
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
virtual void flush() = 0;
virtual size_t readBytes(char *buffer, size_t length) {
size_t count = 0;
while (count < length) {
int c = timedRead();
if (c < 0)
break;
*buffer++ = (char)c;
count++;
}
return count;
}
virtual size_t readBytes(uint8_t *buffer, size_t length) {
return readBytes((char *)buffer, length);
}
virtual String readString() {
String result;
int c;
while ((c = timedRead()) >= 0) {
result += c;
}
return result;
}
void setTimeout(unsigned long) {}
protected:
int timedRead() {
return read();
}
};

View File

@@ -1,5 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "../avr/WString.h"

View File

@@ -1,18 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <Client.h>
#include <Print.h>
#include <Stream.h>
#include <WString.h>
#include <time.h>
inline unsigned long millis() {
return static_cast<unsigned long>(time(NULL));
}
inline void yield() {}

View File

@@ -1,22 +0,0 @@
# StreamUtils - github.com/bblanchon/ArduinoStreamUtils
# Copyright Benoit Blanchon 2019-2021
# MIT License
add_library(Esp8266Core
Client.h
EEPROM.cpp
EEPROM.h
Print.h
Stream.h
WString.h
)
target_include_directories(Esp8266Core
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
target_compile_definitions(Esp8266Core
PUBLIC
ARDUINO_ARCH_ESP8266
)

View File

@@ -1,26 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include "Stream.h"
#include "WString.h"
using IPAddress = String;
class Client : public Stream {
public:
virtual int connect(IPAddress ip, uint16_t port) = 0;
virtual int connect(const char *host, uint16_t port) = 0;
virtual size_t write(uint8_t) = 0;
virtual size_t write(const uint8_t *buf, size_t size) = 0;
virtual int available() = 0;
virtual int read() = 0;
virtual int read(uint8_t *buf, size_t size) = 0;
virtual int peek() = 0;
virtual void flush() = 0;
virtual void stop() = 0;
virtual uint8_t connected() = 0;
virtual operator bool() = 0;
};

View File

@@ -1,19 +0,0 @@
#include "EEPROM.h"
#include <string.h> // memcpy
EEPROMClass EEPROM;
static uint8_t commitedData[512];
static uint8_t pendingData[512];
uint8_t EEPROMClass::read(int address) {
return commitedData[address];
}
void EEPROMClass::write(int address, uint8_t value) {
pendingData[address] = value;
}
void EEPROMClass::commit() {
memcpy(commitedData, pendingData, 512);
}

View File

@@ -1,12 +0,0 @@
#pragma once
#include <stdint.h>
class EEPROMClass {
public:
uint8_t read(int);
void write(int, uint8_t);
void commit();
};
extern EEPROMClass EEPROM;

View File

@@ -1,43 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <WString.h>
#include <stdint.h>
#include <cstring>
struct Print {
virtual size_t write(const uint8_t *buffer, size_t size) = 0;
virtual size_t write(uint8_t data) = 0;
size_t write(const char *buffer, size_t size) {
return write((const uint8_t *)buffer, size);
}
size_t print(const String &s) {
return write(s.c_str(), s.length());
}
size_t print(const char *s) {
return write(s, std::strlen(s));
}
size_t println() {
return 0;
}
template <typename T>
size_t print(const T &value) {
return print(String(value));
}
template <typename T>
size_t println(const T &value) {
return print(value);
}
virtual void flush() {}
};

View File

@@ -1,45 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include "Print.h"
struct Stream : Print {
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
virtual size_t readBytes(char *buffer, size_t length) {
size_t count = 0;
while (count < length) {
int c = timedRead();
if (c < 0)
break;
*buffer++ = (char)c;
count++;
}
return count;
}
virtual size_t readBytes(uint8_t *buffer, size_t length) {
return readBytes((char *)buffer, length);
}
virtual String readString() {
String result;
int c;
while ((c = timedRead()) >= 0) {
result += c;
}
return result;
}
void setTimeout(unsigned long) {}
protected:
int timedRead() {
return read();
}
};

View File

@@ -1,5 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "../avr/WString.h"

View File

@@ -1,18 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <Client.h>
#include <Print.h>
#include <Stream.h>
#include <WString.h>
#include <time.h>
inline unsigned long millis() {
return static_cast<unsigned long>(time(NULL));
}
inline void yield() {}

View File

@@ -1,15 +0,0 @@
# StreamUtils - github.com/bblanchon/ArduinoStreamUtils
# Copyright Benoit Blanchon 2019-2021
# MIT License
add_library(Nrf52Core INTERFACE)
target_include_directories(Nrf52Core
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}
)
target_compile_definitions(Nrf52Core
INTERFACE
ARDUINO_ARCH_NRF52
)

View File

@@ -1,26 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include "Stream.h"
#include "WString.h"
using IPAddress = String;
class Client : public Stream {
public:
virtual int connect(IPAddress ip, uint16_t port) = 0;
virtual int connect(const char *host, uint16_t port) = 0;
virtual size_t write(uint8_t) = 0;
virtual size_t write(const uint8_t *buf, size_t size) = 0;
virtual int available() = 0;
virtual int read() = 0;
virtual int read(uint8_t *buf, size_t size) = 0;
virtual int peek() = 0;
virtual void flush() = 0;
virtual void stop() = 0;
virtual uint8_t connected() = 0;
virtual operator bool() = 0;
};

View File

@@ -1,45 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <WString.h>
#include <stdint.h>
#include <cstring>
struct Print {
virtual size_t write(const uint8_t *buffer, size_t size) = 0;
virtual size_t write(uint8_t data) = 0;
virtual int availableForWrite() {
return 0;
}
size_t write(const char *buffer, size_t size) {
return write((const uint8_t *)buffer, size);
}
size_t print(const String &s) {
return write(s.c_str(), s.length());
}
size_t print(const char *s) {
return write(s, std::strlen(s));
}
size_t println() {
return 0;
}
template <typename T>
size_t print(const T &value) {
return print(String(value));
}
template <typename T>
size_t println(const T &value) {
return print(value);
}
};

View File

@@ -1,45 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include "Print.h"
struct Stream : Print {
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
virtual void flush() {}
size_t readBytes(char *buffer, size_t length) {
size_t count = 0;
while (count < length) {
int c = timedRead();
if (c < 0)
break;
*buffer++ = (char)c;
count++;
}
return count;
}
size_t readBytes(uint8_t *buffer, size_t length) {
return readBytes((char *)buffer, length);
}
String readString() {
String result;
int c;
while ((c = timedRead()) >= 0)
result += c;
return result;
}
void setTimeout(unsigned long) {}
protected:
int timedRead() {
return read();
}
};

View File

@@ -1,5 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "../avr/WString.h"

View File

@@ -1,18 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <Client.h>
#include <Print.h>
#include <Stream.h>
#include <WString.h>
#include <time.h>
inline unsigned long millis() {
return static_cast<unsigned long>(time(NULL));
}
inline void yield() {}

View File

@@ -1,15 +0,0 @@
# StreamUtils - github.com/bblanchon/ArduinoStreamUtils
# Copyright Benoit Blanchon 2019-2021
# MIT License
add_library(SamdCore INTERFACE)
target_include_directories(SamdCore
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}
)
target_compile_definitions(SamdCore
INTERFACE
ARDUINO_ARCH_SAMD
)

View File

@@ -1,26 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include "Stream.h"
#include "WString.h"
using IPAddress = String;
class Client : public Stream {
public:
virtual int connect(IPAddress ip, uint16_t port) = 0;
virtual int connect(const char *host, uint16_t port) = 0;
virtual size_t write(uint8_t) = 0;
virtual size_t write(const uint8_t *buf, size_t size) = 0;
virtual int available() = 0;
virtual int read() = 0;
virtual int read(uint8_t *buf, size_t size) = 0;
virtual int peek() = 0;
virtual void flush() = 0;
virtual void stop() = 0;
virtual uint8_t connected() = 0;
virtual operator bool() = 0;
};

View File

@@ -1,46 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <WString.h>
#include <stdint.h>
#include <cstring>
struct Print {
virtual size_t write(const uint8_t *buffer, size_t size) = 0;
virtual size_t write(uint8_t data) = 0;
virtual void flush() {}
virtual int availableForWrite() {
return 0;
}
size_t write(const char *buffer, size_t size) {
return write((const uint8_t *)buffer, size);
}
size_t print(const String &s) {
return write(s.c_str(), s.length());
}
size_t print(const char *s) {
return write(s, std::strlen(s));
}
size_t println() {
return 0;
}
template <typename T>
size_t print(const T &value) {
return print(String(value));
}
template <typename T>
size_t println(const T &value) {
return print(value);
}
};

View File

@@ -1,44 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include "Print.h"
struct Stream : Print {
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
size_t readBytes(char *buffer, size_t length) {
size_t count = 0;
while (count < length) {
int c = timedRead();
if (c < 0)
break;
*buffer++ = (char)c;
count++;
}
return count;
}
size_t readBytes(uint8_t *buffer, size_t length) {
return readBytes((char *)buffer, length);
}
String readString() {
String result;
int c;
while ((c = timedRead()) >= 0)
result += c;
return result;
}
void setTimeout(unsigned long) {}
protected:
int timedRead() {
return read();
}
};

View File

@@ -1,5 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "../avr/WString.h"

View File

@@ -1,18 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include <Client.h>
#include <Print.h>
#include <Stream.h>
#include <WString.h>
#include <time.h>
inline unsigned long millis() {
return static_cast<unsigned long>(time(NULL));
}
inline void yield() {}

View File

@@ -1,22 +0,0 @@
# StreamUtils - github.com/bblanchon/ArduinoStreamUtils
# Copyright Benoit Blanchon 2019-2021
# MIT License
add_library(Stm32Core
Client.h
EEPROM.cpp
EEPROM.h
Print.h
Stream.h
WString.h
)
target_include_directories(Stm32Core
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
target_compile_definitions(Stm32Core
PUBLIC
ARDUINO_ARCH_STM32
)

View File

@@ -1,28 +0,0 @@
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#pragma once
#include "Stream.h"
#include "WString.h"
using IPAddress = String;
struct Client : Stream {
// Print
virtual size_t write(uint8_t) = 0;
virtual size_t write(const uint8_t *buf, size_t size) = 0;
// Stream
virtual int available() = 0;
virtual int read() = 0;
virtual void flush() = 0;
virtual int connect(IPAddress ip, uint16_t port) = 0;
virtual int connect(const char *host, uint16_t port) = 0;
virtual uint8_t connected() = 0;
virtual void stop() = 0;
virtual operator bool() = 0;
virtual int read(uint8_t *buf, size_t size) = 0;
};

Some files were not shown because too many files have changed in this diff Show More