diff --git a/.gitmodules b/.gitmodules index 9d62de59ac..a1404fb3cd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -217,6 +217,10 @@ path = Sming/Libraries/CS5460/CS5460 url = https://github.com/xxzl0130/CS5460.git ignore = dirty +[submodule "Libraries.CsvReader"] + path = Sming/Libraries/CsvReader + url = https://github.com/mikee47/CsvReader + ignore = dirty [submodule "Libraries.DFRobotDFPlayerMini"] path = Sming/Libraries/DFRobotDFPlayerMini url = https://github.com/DFRobot/DFRobotDFPlayerMini.git diff --git a/Sming/Arch/Esp32/Tools/travis/build.run.sh b/Sming/Arch/Esp32/Tools/travis/build.run.sh deleted file mode 100755 index 16923e6086..0000000000 --- a/Sming/Arch/Esp32/Tools/travis/build.run.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -set -ex # exit with nonzero exit code if anything fails - -$MAKE_PARALLEL Basic_Blink Basic_WiFi HttpServer_ConfigNetwork DEBUG_VERBOSE_LEVEL=3 STRICT=1 -$MAKE_PARALLEL Basic_Ssl ENABLE_SSL=Bearssl DEBUG_VERBOSE_LEVEL=3 STRICT=1 diff --git a/Sming/Arch/Esp32/Tools/travis/build.setup.sh b/Sming/Arch/Esp32/Tools/travis/build.setup.sh deleted file mode 100755 index 98723973bf..0000000000 --- a/Sming/Arch/Esp32/Tools/travis/build.setup.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -set -ex # exit with nonzero exit code if anything fails - -export IDF_PATH=$TRAVIS_BUILD_DIR/opt/esp-idf diff --git a/Sming/Arch/Esp32/Tools/travis/install.sh b/Sming/Arch/Esp32/Tools/travis/install.sh deleted file mode 100755 index 384e489ee0..0000000000 --- a/Sming/Arch/Esp32/Tools/travis/install.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -set -ex # exit with nonzero exit code if anything fails - -if [ "$TRAVIS_OS_NAME" == "linux" ]; then - sudo apt-get install -y git wget flex bison gperf \ - cmake ninja-build ccache libffi-dev libssl-dev dfu-util \ - python3 python3-pip python3-setuptools - sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 10 - mkdir -p $TRAVIS_BUILD_DIR/opt - cd $TRAVIS_BUILD_DIR/opt - git clone -b v4.1 --recursive https://github.com/espressif/esp-idf.git - export IDF_PATH=$TRAVIS_BUILD_DIR/opt/esp-idf - $IDF_PATH/install.sh - - python -m pip install -r $IDF_PATH/requirements.txt -fi diff --git a/Sming/Arch/Esp8266/Tools/travis/build.run.sh b/Sming/Arch/Esp8266/Tools/travis/build.run.sh deleted file mode 100755 index 7719f237b4..0000000000 --- a/Sming/Arch/Esp8266/Tools/travis/build.run.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -set -ex # exit with nonzero exit code if anything fails - -make -C "$SMING_PROJECTS_DIR/samples/HttpServer_FirmwareUpload" python-requirements -$MAKE_PARALLEL samples -make clean samples-clean -$MAKE_PARALLEL Basic_Blink ENABLE_CUSTOM_HEAP=1 DEBUG_VERBOSE_LEVEL=3 -$MAKE_PARALLEL HttpServer_ConfigNetwork ENABLE_CUSTOM_LWIP=2 STRICT=1 diff --git a/Sming/Arch/Esp8266/Tools/travis/build.setup.sh b/Sming/Arch/Esp8266/Tools/travis/build.setup.sh deleted file mode 100755 index 5234ca9f7a..0000000000 --- a/Sming/Arch/Esp8266/Tools/travis/build.setup.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -set -ex # exit with nonzero exit code if anything fails - -unset SPIFFY -unset ESPTOOL2 -unset SDK_BASE - -export PATH=$PATH:$ESP_HOME/xtensa-lx106-elf/bin:$ESP_HOME/utils/ diff --git a/Sming/Arch/Esp8266/Tools/travis/install.sh b/Sming/Arch/Esp8266/Tools/travis/install.sh deleted file mode 100644 index 9f0f866075..0000000000 --- a/Sming/Arch/Esp8266/Tools/travis/install.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -set -ex # exit with nonzero exit code if anything fails - -if [ "$TRAVIS_OS_NAME" == "linux" ]; then - # Old toolchain - TOOLCHAIN=esp-open-sdk-linux-x86_64.tar.gz - wget --no-verbose $SMINGTOOLS/$TOOLCHAIN - tar -zxf $TOOLCHAIN - mkdir -p $TRAVIS_BUILD_DIR/opt/esp-alt-sdk - ln -s $(pwd)/esp-open-sdk/xtensa-lx106-elf $TRAVIS_BUILD_DIR/opt/esp-alt-sdk/. - - # New toolchain - TOOLCHAIN=x86_64-linux-gnu.xtensa-lx106-elf-e6a192b.201211.tar.gz - wget --no-verbose $SMINGTOOLS/$TOOLCHAIN - mkdir -p opt/esp-quick-toolchain - tar -zxf $TOOLCHAIN -C opt/esp-quick-toolchain --totals -fi diff --git a/Sming/Arch/Host/Components/driver/include/driver/os_timer.h b/Sming/Arch/Host/Components/driver/include/driver/os_timer.h index 4502fc2e23..fc8ae7affc 100644 --- a/Sming/Arch/Host/Components/driver/include/driver/os_timer.h +++ b/Sming/Arch/Host/Components/driver/include/driver/os_timer.h @@ -52,7 +52,7 @@ void os_timer_setfn(os_timer_t* ptimer, os_timer_func_t* pfunction, void* parg); static inline uint64_t os_timer_expire(const os_timer_t* ptimer) { - if(ptimer == nullptr || int(ptimer->timer_next) == -1) { + if(ptimer == nullptr || intptr_t(ptimer->timer_next) == -1) { return 0; } return ptimer->timer_expire; diff --git a/Sming/Arch/Host/Components/driver/os_timer.cpp b/Sming/Arch/Host/Components/driver/os_timer.cpp index e546c35256..1d0f77f4dd 100644 --- a/Sming/Arch/Host/Components/driver/os_timer.cpp +++ b/Sming/Arch/Host/Components/driver/os_timer.cpp @@ -67,7 +67,7 @@ void os_timer_disarm(struct os_timer_t* ptimer) { assert(ptimer != nullptr); - if(int(ptimer->timer_next) == -1) { + if(intptr_t(ptimer->timer_next) == -1) { return; } diff --git a/Sming/Arch/Host/Components/esp_hal/include/esp_tasks.h b/Sming/Arch/Host/Components/esp_hal/include/esp_tasks.h index be1d289e63..48882c54da 100644 --- a/Sming/Arch/Host/Components/esp_hal/include/esp_tasks.h +++ b/Sming/Arch/Host/Components/esp_hal/include/esp_tasks.h @@ -6,8 +6,8 @@ extern "C" { #endif -typedef uint32_t os_signal_t; -typedef uint32_t os_param_t; +typedef uintptr_t os_signal_t; +typedef uintptr_t os_param_t; typedef struct { os_signal_t sig; @@ -32,9 +32,9 @@ void host_init_tasks(); // Hook function to process task queues void host_service_tasks(); -typedef void (*host_task_callback_t)(uint32_t param); +typedef void (*host_task_callback_t)(os_param_t param); -bool host_queue_callback(host_task_callback_t callback, uint32_t param); +bool host_queue_callback(host_task_callback_t callback, os_param_t param); #ifdef __cplusplus } diff --git a/Sming/Arch/Host/Components/esp_hal/tasks.cpp b/Sming/Arch/Host/Components/esp_hal/tasks.cpp index bd242df133..1c561564a0 100644 --- a/Sming/Arch/Host/Components/esp_hal/tasks.cpp +++ b/Sming/Arch/Host/Components/esp_hal/tasks.cpp @@ -114,7 +114,7 @@ void host_service_tasks() } } -bool host_queue_callback(host_task_callback_t callback, uint32_t param) +bool host_queue_callback(host_task_callback_t callback, os_param_t param) { return task_queues[HOST_TASK_PRIO]->post(os_signal_t(callback), param); } diff --git a/Sming/Arch/Host/Components/hostlib/startup.cpp b/Sming/Arch/Host/Components/hostlib/startup.cpp index 3fce4bec04..f74fdf3405 100644 --- a/Sming/Arch/Host/Components/hostlib/startup.cpp +++ b/Sming/Arch/Host/Components/hostlib/startup.cpp @@ -246,6 +246,8 @@ int main(int argc, char* argv[]) } } + m_setPuts(&host_nputs); + host_debug_i("\nWelcome to the Sming Host emulator\n\n"); auto i = get_first_non_option(); @@ -309,7 +311,7 @@ int main(int argc, char* argv[]) pause(config.exitpause); // Avoid issues with debug statements whilst running exit handlers - m_setPuts(nullptr); + m_setPuts(&host_nputs); return exitCode; } diff --git a/Sming/Arch/Host/Tools/travis/build.run.sh b/Sming/Arch/Host/Tools/travis/build.run.sh deleted file mode 100755 index 1b24170fc9..0000000000 --- a/Sming/Arch/Host/Tools/travis/build.run.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -set -ex # exit with nonzero exit code if anything fails - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" - -if [[ $CHECK_SCA -eq 1 ]]; then - $DIR/coverity-scan.sh -else - $MAKE_PARALLEL Basic_Blink Basic_DateTime Basic_Delegates Basic_Interrupts Basic_ProgMem Basic_Serial Basic_Servo Basic_Ssl LiveDebug DEBUG_VERBOSE_LEVEL=3 -fi - -# Build and run tests -export SMING_TARGET_OPTIONS='--flashfile=$(FLASH_BIN) --flashsize=$(SPI_SIZE)' -$MAKE_PARALLEL tests - -# Build the documentation -mv $SMING_PROJECTS_DIR/samples .. -mv $SMING_PROJECTS_DIR/tests .. -unset SMING_PROJECTS_DIR -$SMING_HOME/../Tools/install.sh doc -make docs V=1 diff --git a/Sming/Arch/Host/Tools/travis/build.setup.sh b/Sming/Arch/Host/Tools/travis/build.setup.sh deleted file mode 100755 index 6820d10aa4..0000000000 --- a/Sming/Arch/Host/Tools/travis/build.setup.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -set -ex # exit with nonzero exit code if anything fails - -# Check coding style -make cs -DIFFS=$(git diff) -if [ "$DIFFS" != "" ]; then - echo "!!! Coding Style issues Found!!!" - echo " Run: 'make cs' to fix them. " - echo "$DIFFS" - exit 1 -fi - -# Check if we could run static code analysis -CHECK_SCA=0 -if [[ $TRAVIS_TAG != "" || ( $TRAVIS_COMMIT_MESSAGE == *"[scan:coverity]"* && $TRAVIS_PULL_REQUEST != "true" ) ]]; then - CHECK_SCA=1 -fi diff --git a/Sming/Arch/Host/Tools/travis/coverity-scan.sh b/Sming/Arch/Host/Tools/travis/coverity-scan.sh deleted file mode 100755 index 2f74499e34..0000000000 --- a/Sming/Arch/Host/Tools/travis/coverity-scan.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/bash - -set -e - -COVERITY_SCAN_PROJECT_NAME=${TRAVIS_REPO_SLUG} -COVERITY_SCAN_NOTIFICATION_EMAIL="slaff@attachix.com" -COVERITY_SCAN_BUILD_COMMAND="$MAKE_PARALLEL dist-clean Basic_Blink Basic_DateTime Basic_Delegates Basic_Interrupts Basic_ProgMem Basic_Serial Basic_Servo Basic_Ssl HttpServer_WebSockets SMING_ARCH=Host DEBUG_VERBOSE_LEVEL=3" - -# Environment check -[ -z "$COVERITY_SCAN_PROJECT_NAME" ] && echo "ERROR: COVERITY_SCAN_PROJECT_NAME must be set" && exit 1 -[ -z "$COVERITY_SCAN_NOTIFICATION_EMAIL" ] && echo "ERROR: COVERITY_SCAN_NOTIFICATION_EMAIL must be set" && exit 1 -[ -z "$COVERITY_SCAN_BUILD_COMMAND" ] && echo "ERROR: COVERITY_SCAN_BUILD_COMMAND must be set" && exit 1 -[ -z "$COVERITY_SCAN_TOKEN" ] && echo "ERROR: COVERITY_SCAN_TOKEN must be set" && exit 1 - -PLATFORM=$(uname) -TOOL_ARCHIVE=/tmp/cov-analysis-${PLATFORM}.tgz -TOOL_URL=https://scan.coverity.com/download/${PLATFORM} -TOOL_BASE=/tmp/coverity-scan-analysis -UPLOAD_URL="https://scan.coverity.com/builds" -SCAN_URL="https://scan.coverity.com" - -# Do not run on pull requests -if [ "${TRAVIS_PULL_REQUEST}" = "true" ]; then - echo -e "\033[33;1mINFO: Skipping Coverity Analysis: branch is a pull request.\033[0m" - exit 0 -fi - -# Verify upload is permitted -permit=true -AUTH_RES=$(curl -s --form project="$COVERITY_SCAN_PROJECT_NAME" --form token="$COVERITY_SCAN_TOKEN" $SCAN_URL/api/upload_permitted) -if [ "$AUTH_RES" = "Access denied" ]; then - echo -e "\033[33;1mCoverity Scan API access denied. Check COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN.\033[0m" - exit 1 -else - AUTH=$(echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['upload_permitted']") - if [ "$AUTH" = "true" ]; then - echo -e "\033[33;1mCoverity Scan analysis authorized per quota.\033[0m" - else - WHEN=$(echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['next_upload_permitted_at']") - echo -e "\033[33;1mOops!Coverity Scan analysis engine NOT authorized until $WHEN.\033[0m" - permit=false - fi -fi - -if [ "$permit" = true ]; then -if [ ! -d $TOOL_BASE ]; then - # Download Coverity Scan Analysis Tool - if [ ! -e $TOOL_ARCHIVE ]; then - echo -e "\033[33;1mDownloading Coverity Scan Analysis Tool...\033[0m" - wget -nv -O $TOOL_ARCHIVE $TOOL_URL --post-data "project=$COVERITY_SCAN_PROJECT_NAME&token=$COVERITY_SCAN_TOKEN" - fi - - # Extract Coverity Scan Analysis Tool - echo -e "\033[33;1mExtracting Coverity Scan Analysis Tool...\033[0m" - mkdir -p $TOOL_BASE - CURRENT_DIR=$(pwd) - cd $TOOL_BASE - tar xzf $TOOL_ARCHIVE - cd $CURRENT_DIR -fi - -TOOL_DIR=$(find $TOOL_BASE -type d -name 'cov-analysis*') -export PATH=$TOOL_DIR/bin:$PATH - -# Build - -echo -e "\033[33;1mRunning Coverity Scan Analysis Tool...\033[0m" -COV_BUILD_OPTIONS="" -#COV_BUILD_OPTIONS="--return-emit-failures 8 --parse-error-threshold 85" -RESULTS_DIR="cov-int" -eval "${COVERITY_SCAN_BUILD_COMMAND_PREPEND}" -COVERITY_UNSUPPORTED=1 cov-build --dir $RESULTS_DIR $COV_BUILD_OPTIONS $COVERITY_SCAN_BUILD_COMMAND -cov-import-scm --dir $RESULTS_DIR --scm git --log $RESULTS_DIR/scm_log.txt 2>&1 - -# Upload results -echo -e "\033[33;1mTarring Coverity Scan Analysis results...\033[0m" -RESULTS_ARCHIVE=analysis-results.tgz -tar czf $RESULTS_ARCHIVE $RESULTS_DIR -SHA=$(git rev-parse --short HEAD) - -echo -e "\033[33;1mUploading Coverity Scan Analysis results...\033[0m" -response=$(curl \ - --silent --write-out "\n%{http_code}\n" \ - --form project=$COVERITY_SCAN_PROJECT_NAME \ - --form token=$COVERITY_SCAN_TOKEN \ - --form email=$COVERITY_SCAN_NOTIFICATION_EMAIL \ - --form file=@$RESULTS_ARCHIVE \ - --form version=$SHA \ - --form description="Travis CI build" \ - $UPLOAD_URL) -status_code=$(echo "$response" | sed -n '$p') -if [ "$status_code" -ge "400" ]; then - TEXT=$(echo "$response" | sed '$d') - echo -e "\033[33;1mCoverity Scan upload failed: $TEXT. Status code: $status_code.\033[0m" - exit 1 -fi -fi diff --git a/Sming/Arch/Host/Tools/travis/install.sh b/Sming/Arch/Host/Tools/travis/install.sh deleted file mode 100755 index 70495ca431..0000000000 --- a/Sming/Arch/Host/Tools/travis/install.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -set -ex # exit with nonzero exit code if anything fails - -sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-8 200 -sudo rm -f /usr/local/clang-7.0.0/bin/clang-format - -python3 -m pip install -q --upgrade pip - -if [ "$BUILD_DOCS" == "1" ]; then - python3 -m pip install -q -r $TRAVIS_BUILD_DIR/docs/requirements.txt -fi diff --git a/Sming/Arch/Host/standard.hw b/Sming/Arch/Host/standard.hw index 7244be0578..287e348737 100644 --- a/Sming/Arch/Host/standard.hw +++ b/Sming/Arch/Host/standard.hw @@ -3,7 +3,12 @@ "arch": "Host", "bootloader_size": "0x2000", "partition_table_offset": "0x2000", - "options": ["4m"], + "devices": { + "spiFlash": { + "type": "flash", + "size": "4M" + } + }, "partitions": { "rom0": { "address": "0x008000", diff --git a/Sming/Arch/Rp2040/standard.hw b/Sming/Arch/Rp2040/standard.hw index d143cd3ba0..2955c37e9d 100644 --- a/Sming/Arch/Rp2040/standard.hw +++ b/Sming/Arch/Rp2040/standard.hw @@ -4,9 +4,12 @@ "arch": "Rp2040", "bootloader_size": 0, "partition_table_offset": "self.devices[0].size - 0x1000", - "options": [ - "2m" - ], + "devices": { + "spiFlash": { + "type": "flash", + "size": "2M" + } + }, "partitions": { "rom0": { "address": 0, diff --git a/Sming/Components/Network/Arch/Host/Platform/StationImpl.cpp b/Sming/Components/Network/Arch/Host/Platform/StationImpl.cpp index 25a71a9021..8b496710a4 100644 --- a/Sming/Components/Network/Arch/Host/Platform/StationImpl.cpp +++ b/Sming/Components/Network/Arch/Host/Platform/StationImpl.cpp @@ -89,8 +89,8 @@ void StationImpl::initialise(netif* nif) } auto netif_callback = [](netif* nif) { - host_queue_callback([](uint32_t param) { station.statusCallback(reinterpret_cast(param)); }, - uint32_t(nif)); + host_queue_callback([](os_param_t param) { station.statusCallback(reinterpret_cast(param)); }, + os_param_t(nif)); }; netif_set_status_callback(nif, netif_callback); @@ -328,7 +328,7 @@ bool StationImpl::startScan(ScanCompletedDelegate scanCompleted) } host_queue_callback( - [](uint32_t param) { + [](os_param_t param) { auto self = reinterpret_cast(param); BssList list; for(const auto& info : apInfoList) { @@ -336,7 +336,7 @@ bool StationImpl::startScan(ScanCompletedDelegate scanCompleted) } self->scanCompletedCallback(true, list); }, - uint32_t(this)); + os_param_t(this)); return true; } diff --git a/Sming/Components/Network/src/Data/Stream/ChunkedStream.cpp b/Sming/Components/Network/src/Data/Stream/ChunkedStream.cpp index be8df057d3..8b8c14b0ce 100644 --- a/Sming/Components/Network/src/Data/Stream/ChunkedStream.cpp +++ b/Sming/Components/Network/src/Data/Stream/ChunkedStream.cpp @@ -25,7 +25,8 @@ size_t ChunkedStream::transform(const uint8_t* source, size_t sourceLength, uint } // Header - unsigned offset = m_snprintf(reinterpret_cast(target), targetLength, "%X\r\n", sourceLength); + unsigned offset = + m_snprintf(reinterpret_cast(target), targetLength, "%X\r\n", static_cast(sourceLength)); // Content memcpy(target + offset, source, sourceLength); diff --git a/Sming/Components/Storage/src/include/Storage/SysMem.h b/Sming/Components/Storage/src/include/Storage/SysMem.h index 7b6f20361d..1193e5722c 100644 --- a/Sming/Components/Storage/src/include/Storage/SysMem.h +++ b/Sming/Components/Storage/src/include/Storage/SysMem.h @@ -80,7 +80,7 @@ class SysMem : public Device */ Partition add(const String& name, const FSTR::ObjectBase& fstr, Partition::FullType type) { - return PartitionTable::add(name, type, reinterpret_cast(fstr.data()), fstr.size(), + return PartitionTable::add(name, type, reinterpret_cast(fstr.data()), fstr.size(), Partition::Flag::readOnly); } }; diff --git a/Sming/Components/rboot/include/Network/RbootHttpUpdater.h b/Sming/Components/rboot/include/Network/RbootHttpUpdater.h index fda0ce60c8..c83f13bf95 100644 --- a/Sming/Components/rboot/include/Network/RbootHttpUpdater.h +++ b/Sming/Components/rboot/include/Network/RbootHttpUpdater.h @@ -36,7 +36,7 @@ class RbootHttpUpdater : protected HttpClient size_t size; // << max allowed size std::unique_ptr stream; // (optional) output stream to use. - Item(String url, uint32_t targetOffset, size_t size, RbootOutputStream* stream) + Item(String url, size_t targetOffset, size_t size, RbootOutputStream* stream) : url(url), targetOffset(targetOffset), size(size), stream(stream) { } @@ -99,7 +99,8 @@ class RbootHttpUpdater : protected HttpClient return false; } - return items.addNew(new Item{firmwareFileUrl, stream->getStartAddress(), stream->getMaxLength(), stream}); + return items.addNew( + new Item{firmwareFileUrl, uint32_t(stream->getStartAddress()), stream->getMaxLength(), stream}); } void start(); diff --git a/Sming/Components/ssl/Axtls/AxContext.cpp b/Sming/Components/ssl/Axtls/AxContext.cpp index 7283d3d910..03195386d1 100644 --- a/Sming/Components/ssl/Axtls/AxContext.cpp +++ b/Sming/Components/ssl/Axtls/AxContext.cpp @@ -89,7 +89,7 @@ Connection* AxContext::createClient(tcp_pcb* tcp) auto id = session.getSessionId(); auto connection = new AxConnection(*this, tcp); auto client = - ssl_client_new(context, int(connection), id ? id->getValue() : nullptr, id ? id->getLength() : 0, ssl_ext); + ssl_client_new(context, intptr_t(connection), id ? id->getValue() : nullptr, id ? id->getLength() : 0, ssl_ext); if(client == nullptr) { ssl_ext_free(ssl_ext); delete connection; @@ -105,7 +105,7 @@ Connection* AxContext::createServer(tcp_pcb* tcp) assert(context != nullptr); auto connection = new AxConnection(*this, tcp); - auto server = ssl_server_new(context, int(connection)); + auto server = ssl_server_new(context, intptr_t(connection)); if(server == nullptr) { delete connection; return nullptr; diff --git a/Sming/Core/CallbackTimer.h b/Sming/Core/CallbackTimer.h index f56ef2dc58..89eed46d0a 100644 --- a/Sming/Core/CallbackTimer.h +++ b/Sming/Core/CallbackTimer.h @@ -44,7 +44,7 @@ template struct CallbackTimerApi { String s; s += typeName(); s += '@'; - s += String(uint32_t(this), HEX); + s += String(uintptr_t(this), HEX); return s; } diff --git a/Sming/Core/Data/Buffer/CircularBuffer.h b/Sming/Core/Data/Buffer/CircularBuffer.h index fad71b793e..ec1c63e0fd 100644 --- a/Sming/Core/Data/Buffer/CircularBuffer.h +++ b/Sming/Core/Data/Buffer/CircularBuffer.h @@ -80,7 +80,7 @@ class CircularBuffer : public ReadWriteStream */ String id() const override { - return String(reinterpret_cast(&buffer), HEX); + return String(reinterpret_cast(&buffer), HEX); } size_t write(uint8_t charToWrite) override; diff --git a/Sming/Core/Data/CStringArray.h b/Sming/Core/Data/CStringArray.h index 27afb9a66c..3b192c6b54 100644 --- a/Sming/Core/Data/CStringArray.h +++ b/Sming/Core/Data/CStringArray.h @@ -89,6 +89,14 @@ class CStringArray : private String return *this; } + /** + * @brief Give up underlying String object to caller so it can be manipulated + */ + String release() + { + return std::move(*this); + } + /** @brief Append a new string (or array of strings) to the end of the array * @param str * @param length Length of new string in array (default is length of str) @@ -127,7 +135,7 @@ class CStringArray : private String * @brief Append numbers, etc. to the array * @param value char, int, float, etc. as supported by String */ - template CStringArray& operator+=(T value) + template CStringArray& operator+=(const T& value) { add(String(value)); return *this; diff --git a/Sming/Core/Data/CsvReader.cpp b/Sming/Core/Data/CsvReader.cpp deleted file mode 100644 index 569ce02a0b..0000000000 --- a/Sming/Core/Data/CsvReader.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/SmingHub/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - * - * CsvReader.cpp - * - * @author: 2021 - Mikee47 - * - ****/ - -#include "CsvReader.h" -#include - -void CsvReader::reset() -{ - source->seekFrom(0, SeekOrigin::Start); - if(!userHeadingsProvided) { - readRow(); - headings = row; - } - row = nullptr; -} - -bool CsvReader::readRow() -{ - constexpr size_t blockSize{512}; - - String buffer(std::move(reinterpret_cast(row))); - constexpr char quoteChar{'"'}; - enum class FieldKind { - unknown, - quoted, - unquoted, - }; - FieldKind fieldKind{}; - bool escape{false}; - bool quote{false}; - char lc{'\0'}; - unsigned writepos{0}; - - while(true) { - if(buffer.length() == maxLineLength) { - debug_w("[CSV] Line buffer limit reached %u", maxLineLength); - return false; - } - size_t buflen = std::min(writepos + blockSize, maxLineLength); - if(!buffer.setLength(buflen)) { - debug_e("[CSV] Out of memory %u", buflen); - return false; - } - auto len = source->readBytes(buffer.begin() + writepos, buflen - writepos); - if(len == 0) { - if(writepos == 0) { - return false; - } - buffer.setLength(writepos); - row = std::move(buffer); - return true; - } - buflen = writepos + len; - unsigned readpos = writepos; - - for(; readpos < buflen; ++readpos) { - char c = buffer[readpos]; - if(escape) { - switch(c) { - case 'n': - c = '\n'; - break; - case 'r': - c = '\r'; - break; - case 't': - c = '\t'; - break; - default:; - // Just accept character - } - escape = false; - } else { - if(fieldKind == FieldKind::unknown) { - if(c == quoteChar) { - fieldKind = FieldKind::quoted; - quote = true; - lc = '\0'; - continue; - } - fieldKind = FieldKind::unquoted; - } - if(c == quoteChar) { - quote = !quote; - if(fieldKind == FieldKind::quoted) { - if(lc == quoteChar) { - buffer[writepos++] = c; - lc = '\0'; - } else { - lc = c; - } - continue; - } - } else if(c == '\\') { - escape = true; - continue; - } else if(!quote) { - if(c == fieldSeparator) { - c = '\0'; - fieldKind = FieldKind::unknown; - } else if(c == '\r') { - continue; - } else if(c == '\n') { - source->seekFrom(readpos + 1 - buflen, SeekOrigin::Current); - buffer.setLength(writepos); - row = std::move(buffer); - return true; - } - } - } - buffer[writepos++] = c; - lc = c; - } - } -} diff --git a/Sming/Core/Data/CsvReader.h b/Sming/Core/Data/CsvReader.h index 596a62a27e..2fcd76036a 100644 --- a/Sming/Core/Data/CsvReader.h +++ b/Sming/Core/Data/CsvReader.h @@ -12,132 +12,4 @@ #pragma once -#include "Stream/DataSourceStream.h" -#include "CStringArray.h" -#include - -/** - * @brief Class to parse a CSV file - * - * Spec: https://www.ietf.org/rfc/rfc4180.txt - * - * 1. Each record is located on a separate line - * 2. Line ending for last record in the file is optional - * 3. Field headings are provided either in the source data or in constructor (but not both) - * 4. Fields separated with ',' and whitespace considered part of field content - * 5. Fields may or may not be quoted - if present, will be removed during parsing - * 6. Fields may contain line breaks, quotes or commas - * 7. Quotes may be escaped thus "" if field itself is quoted - * - * Additional features: - * - * - Line breaks can be \n or \r\n - * - Escapes codes within fields will be converted: \n \r \t \", \\ - * - Field separator can be changed in constructor - */ -class CsvReader -{ -public: - /** - * @brief Construct a CSV reader - * @param source Stream to read CSV text from - * @param fieldSeparator - * @param headings Required if source data does not contain field headings as first row - * @param maxLineLength Limit size of buffer to guard against malformed data - */ - CsvReader(IDataSourceStream* source, char fieldSeparator = ',', const CStringArray& headings = nullptr, - size_t maxLineLength = 2048) - : source(source), fieldSeparator(fieldSeparator), userHeadingsProvided(headings), maxLineLength(maxLineLength), - headings(headings) - { - reset(); - } - - /** - * @brief Reset reader to start of CSV file - * - * Cursor is set to 'before start'. - * Call 'next()' to fetch first record. - */ - void reset(); - - /** - * @brief Seek to next record - */ - bool next() - { - return readRow(); - } - - /** - * @brief Get number of columns - */ - unsigned count() const - { - return headings.count(); - } - - /** - * @brief Get a value from the current row - * @param index Column index, starts at 0 - * @retval const char* nullptr if index is not valid - */ - const char* getValue(unsigned index) - { - return row[index]; - } - - /** - * @brief Get a value from the current row - * @param index Column name - * @retval const char* nullptr if name is not found - */ - const char* getValue(const char* name) - { - return getValue(getColumn(name)); - } - - /** - * @brief Get index of column given its name - * @param name Column name to find - * @retval int -1 if name is not found - */ - int getColumn(const char* name) - { - return headings.indexOf(name); - } - - /** - * @brief Determine if row is valid - */ - explicit operator bool() const - { - return bool(row); - } - - /** - * @brief Get headings - */ - const CStringArray& getHeadings() const - { - return headings; - } - - /** - * @brief Get current row - */ - const CStringArray& getRow() const - { - return row; - } - -private: - bool readRow(); - - std::unique_ptr source; - char fieldSeparator; - bool userHeadingsProvided; - size_t maxLineLength; - CStringArray headings; - CStringArray row; -}; +static_assert(false, "CsvReader class has been moved to the CsvReader library."); diff --git a/Sming/Core/Task.h b/Sming/Core/Task.h index 1c04dc72e0..bb82f73896 100644 --- a/Sming/Core/Task.h +++ b/Sming/Core/Task.h @@ -164,12 +164,12 @@ class Task } scheduled = System.queueCallback( - [](uint32_t param) { + [](void* param) { auto task = reinterpret_cast(param); task->scheduled = false; task->service(); }, - uint32_t(this)); + this); return scheduled; } diff --git a/Sming/Libraries/CsvReader b/Sming/Libraries/CsvReader new file mode 160000 index 0000000000..8f4d416442 --- /dev/null +++ b/Sming/Libraries/CsvReader @@ -0,0 +1 @@ +Subproject commit 8f4d416442292927d15fe00d80130fb2fc7d8bb6 diff --git a/Sming/Libraries/FlashIP b/Sming/Libraries/FlashIP index 1e67f9a47d..5d1dae0541 160000 --- a/Sming/Libraries/FlashIP +++ b/Sming/Libraries/FlashIP @@ -1 +1 @@ -Subproject commit 1e67f9a47d9e9f479c1b2c34d36800994515c8c2 +Subproject commit 5d1dae05417171ea23081b44a5401661bbefb599 diff --git a/Sming/Libraries/GoogleCast b/Sming/Libraries/GoogleCast index 4a95b75612..930d641cd9 160000 --- a/Sming/Libraries/GoogleCast +++ b/Sming/Libraries/GoogleCast @@ -1 +1 @@ -Subproject commit 4a95b756127799ef25697fa6bca28c35094eec52 +Subproject commit 930d641cd93862b554633e860afb6104de41b3c1 diff --git a/Sming/Libraries/IOControl b/Sming/Libraries/IOControl index cd42d86b26..d297b3ae71 160000 --- a/Sming/Libraries/IOControl +++ b/Sming/Libraries/IOControl @@ -1 +1 @@ -Subproject commit cd42d86b26901af9fedddb04a933807c5206ee5d +Subproject commit d297b3ae715e5fac82425e7c316cbc0cdd919cd4 diff --git a/Sming/Libraries/Spiffs/src/FileSystem.cpp b/Sming/Libraries/Spiffs/src/FileSystem.cpp index 7bc5f373cb..6e79df5ee8 100644 --- a/Sming/Libraries/Spiffs/src/FileSystem.cpp +++ b/Sming/Libraries/Spiffs/src/FileSystem.cpp @@ -152,7 +152,7 @@ int FileSystem::mount() .hal_erase_f = f_erase, .phys_size = uint32_t(partSize), .phys_addr = 0, - .phys_erase_block = partition.getBlockSize(), + .phys_erase_block = uint32_t(partition.getBlockSize()), .log_block_size = logicalBlockSize, .log_page_size = LOG_PAGE_SIZE, }; diff --git a/Sming/Libraries/TFT_S1D13781 b/Sming/Libraries/TFT_S1D13781 index 3d5ddab2f7..04e19b5003 160000 --- a/Sming/Libraries/TFT_S1D13781 +++ b/Sming/Libraries/TFT_S1D13781 @@ -1 +1 @@ -Subproject commit 3d5ddab2f7dec460ce649ca69bc5ab625c2c7215 +Subproject commit 04e19b5003be0d1edacdb07b9b511e3b1de60af1 diff --git a/Sming/Libraries/UPnP b/Sming/Libraries/UPnP index 2700835f8e..17ea2953be 160000 --- a/Sming/Libraries/UPnP +++ b/Sming/Libraries/UPnP @@ -1 +1 @@ -Subproject commit 2700835f8ef23efd415751db0a7843b1626cb8da +Subproject commit 17ea2953be95336e1b0cae3090fe992caab56b0a diff --git a/Sming/Platform/System.cpp b/Sming/Platform/System.cpp index c490fc3018..63a08d95a9 100644 --- a/Sming/Platform/System.cpp +++ b/Sming/Platform/System.cpp @@ -46,9 +46,9 @@ void SystemClass::taskHandler(os_event_t* event) --taskCount; restoreInterrupts(level); #endif - auto callback = reinterpret_cast(event->sig); + auto callback = reinterpret_cast(event->sig); if(callback != nullptr) { - callback(event->par); + callback(reinterpret_cast(event->par)); } } @@ -74,7 +74,7 @@ bool SystemClass::initialize() return true; } -bool SystemClass::queueCallback(TaskCallback32 callback, uint32_t param) +bool SystemClass::queueCallback(TaskCallback callback, void* param) { if(callback == nullptr) { return false; @@ -89,7 +89,8 @@ bool SystemClass::queueCallback(TaskCallback32 callback, uint32_t param) restoreInterrupts(level); #endif - return system_os_post(USER_TASK_PRIO_1, reinterpret_cast(callback), param); + return system_os_post(USER_TASK_PRIO_1, reinterpret_cast(callback), + reinterpret_cast(param)); } bool SystemClass::queueCallback(TaskDelegate callback) diff --git a/Sming/Platform/System.h b/Sming/Platform/System.h index ac5467527b..c4cca4fd9f 100644 --- a/Sming/Platform/System.h +++ b/Sming/Platform/System.h @@ -191,15 +191,15 @@ class SystemClass * Note also that this method is typically called from interrupt context so must avoid things * like heap allocation, etc. */ - static bool IRAM_ATTR queueCallback(TaskCallback32 callback, uint32_t param = 0); + static bool IRAM_ATTR queueCallback(TaskCallback32 callback, uint32_t param = 0) + { + return queueCallback(reinterpret_cast(callback), reinterpret_cast(param)); + } /** * @brief Queue a deferred callback, with optional void* parameter */ - __forceinline static bool IRAM_ATTR queueCallback(TaskCallback callback, void* param = nullptr) - { - return queueCallback(reinterpret_cast(callback), reinterpret_cast(param)); - } + static bool IRAM_ATTR queueCallback(TaskCallback callback, void* param = nullptr); /** * @brief Queue a deferred callback with no callback parameter diff --git a/Sming/Wiring/FakePgmSpace.h b/Sming/Wiring/FakePgmSpace.h index fae56002c7..82fd39066b 100644 --- a/Sming/Wiring/FakePgmSpace.h +++ b/Sming/Wiring/FakePgmSpace.h @@ -31,7 +31,7 @@ extern "C" { /** * @brief determines if the given value is aligned to a word (4-byte) boundary */ -#define IS_ALIGNED(_x) (((uint32_t)(_x)&3) == 0) +#define IS_ALIGNED(_x) (((uintptr_t)(_x)&3) == 0) /** * @brief Align a size up to the nearest word boundary diff --git a/Sming/Wiring/WString.cpp b/Sming/Wiring/WString.cpp index b2d3b83aac..401851540b 100644 --- a/Sming/Wiring/WString.cpp +++ b/Sming/Wiring/WString.cpp @@ -276,16 +276,14 @@ void String::move(String& rhs) (void)reserve(rhs_len); } - // If we already have capacity, copy the data and free rhs buffers - if(capacity() >= rhs_len) { + // If we have more capacity than the target, copy the data and free rhs buffers + if(rhs.sso.set || capacity() > rhs.capacity()) { memmove(buffer(), rhs.buffer(), rhs_len); setlen(rhs_len); rhs.invalidate(); return; } - assert(!rhs.sso.set); - // We don't have enough space so perform a pointer swap if(!sso.set) { free(ptr.buffer); diff --git a/Sming/building.rst b/Sming/building.rst index 3a8cc8d18b..39a3f4b44b 100644 --- a/Sming/building.rst +++ b/Sming/building.rst @@ -200,8 +200,9 @@ Directory layout The main Sming repo. is laid out like this:: |_ sming/ - |_ .appveyor.yml CI testing - |_ .travis.yml CI testing + |_ .github.yml CI testing + |_ .clang-format.yml Spec for clang-format tool + |_ .clang-tidy.yml Spec for clang-tidy tool |_ .readthedocs.yml Documentation build |_ lgtm.yml CI Static code analysis |_ docs/ Sming documentation @@ -231,7 +232,11 @@ The main Sming repo. is laid out like this:: | |_ Components/ Framework support code, not to be used directly by applications | |_ Core/ Main framework core | |_ Libraries/ Arduino Libraries + | | |_ .patches Patch information applied when pulling in library submodules | | |_ ... + | | | |_ README.rst Mandatory README file (can be README.md) + | | | |_ samples/ Optional library sample applications + | | | |_ test/ Optional CI test application | |_ out/ All generated shared files are written here | | |_ Esp8266/ The Arch | | | |_ debug/ The build type @@ -248,16 +253,20 @@ The main Sming repo. is laid out like this:: | | |_ ... | |_ System/ Common framework low-level system code | | |_ include/ - | |_ Wiring/ + | |_ Wiring/ Arduino wiring framework classes (ish) | |_ ... - |_ tests/ Integration test applications + |_ tests/ Primary integration test applications |_ ... |_ Tools/ |_ ci CI testing |_ Docker |_ ide IDE environment support tools |_ Python Shared python scripts + |_ spelling Framework spell-checking tools |_ travis CI testing + |_ install.cmd Windows install script + |_ install.sh Linux install script + |_ export.sh Configure default environment variables A typical Project looks like this:: diff --git a/Tools/Docker/appveyor/Dockerfile-Linux b/Tools/Docker/appveyor/Dockerfile-Linux deleted file mode 100644 index eec6f2a32c..0000000000 --- a/Tools/Docker/appveyor/Dockerfile-Linux +++ /dev/null @@ -1,9 +0,0 @@ -# Build an appveyor Linux container image with Sming tools installed -FROM appveyor/build-image:minimal-ubuntu-20.04 -ARG SMING_REPO=https://github.com/SmingHub/Sming -ARG SMING_BRANCH=develop -WORKDIR /tmp -RUN git clone ${SMING_REPO} --branch ${SMING_BRANCH} --depth 1 sming && \ - pwsh "sming/Tools/Docker/appveyor/setup.ps1" -USER appveyor -CMD [ "/bin/bash", "/scripts/entrypoint.sh" ] diff --git a/Tools/Docker/appveyor/Dockerfile-Windows b/Tools/Docker/appveyor/Dockerfile-Windows deleted file mode 100644 index 215964f820..0000000000 --- a/Tools/Docker/appveyor/Dockerfile-Windows +++ /dev/null @@ -1,7 +0,0 @@ -# Build an appveyor Windows container image with Sming tools installed -FROM appveyor/build-image:minimal-windowsservercore-ltsc2019 -ARG SMING_REPO=https://github.com/SmingHub/Sming -ARG SMING_BRANCH=develop -WORKDIR /tmp -RUN git clone %SMING_REPO% --branch %SMING_BRANCH% --depth 1 sming && \ - pwsh "sming/Tools/Docker/appveyor/setup.ps1" diff --git a/Tools/Docker/appveyor/README.rst b/Tools/Docker/appveyor/README.rst deleted file mode 100644 index 41c38392ef..0000000000 --- a/Tools/Docker/appveyor/README.rst +++ /dev/null @@ -1,5 +0,0 @@ -Appveyor Build Images -===================== - -See https://sming.readthedocs.io/en/latest/information/develop/ci.html for details. - diff --git a/Tools/Docker/appveyor/setup.ps1 b/Tools/Docker/appveyor/setup.ps1 deleted file mode 100644 index 66fcd84354..0000000000 --- a/Tools/Docker/appveyor/setup.ps1 +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env pwsh -# -# Called indirectly via appveyor build script -# - -cd /tmp -$env:SMING_HOME = "$(pwd)/sming/Sming" -. sming/Tools/ci/setenv.ps1 - -if($IsWindows) { - choco install -y --no-progress python3 --version 3.9 - choco install -y --no-progress cmake llvm - sming/Tools/ci/install.cmd all doc -} else { - $env:EXTRA_PACKAGES = "clang iproute2" - sming/Tools/install.sh all doc fonts -} - -pushd "$env:IDF_PATH" -git submodule update --init --recursive -popd - -Remove-Item sming, downloads -Force -Recurse diff --git a/Tools/ci/library/appveyor.txt b/Tools/ci/library/appveyor.txt deleted file mode 100644 index 47561c9f9f..0000000000 --- a/Tools/ci/library/appveyor.txt +++ /dev/null @@ -1,42 +0,0 @@ -image: -- Ubuntu2004 -- Visual Studio 2019 - -environment: - SMING_REPO: https://github.com/SmingHub/Sming - SMING_BRANCH: develop - - matrix: - - SMING_ARCH: Host - - - SMING_ARCH: Esp8266 - - - SMING_ARCH: Esp32 - SMING_SOC: esp32 - - - SMING_ARCH: Esp32 - SMING_SOC: esp32s2 - - - SMING_ARCH: Esp32 - SMING_SOC: esp32c3 - - - SMING_ARCH: Rp2040 - -install: - - ps: | - Start-Process -FilePath git -ArgumentList "clone $env:SMING_REPO -b $env:SMING_BRANCH --depth 1 sming" -Wait -NoNewWindow - $env:COMPONENT_SEARCH_DIRS = (resolve-path "$pwd/..").path - $env:CI_MAKEFILE = (resolve-path "$pwd/sming/Tools/ci/library/Makefile").path - . sming/Tools/ci/setenv.ps1 - - - cmd: | - if "%APPVEYOR_BUILD_WORKER_CLOUD%"=="" sming\Tools\ci\install.cmd %SMING_ARCH% - - - sh: | - if [ -z "$APPVEYOR_BUILD_WORKER_CLOUD" ]; then - . sming/Tools/ci/install.sh ${SMING_ARCH,,} - fi - -build_script: - - sh: make -j$(nproc) -f $CI_MAKEFILE - - cmd: make -j%NUMBER_OF_PROCESSORS% -f %CI_MAKEFILE% diff --git a/docs/source/information/develop/ci.rst b/docs/source/information/develop/ci.rst index 4c55e692d2..6aa647082e 100644 --- a/docs/source/information/develop/ci.rst +++ b/docs/source/information/develop/ci.rst @@ -25,12 +25,6 @@ Github Actions We use Github Actions to manage all test builds. This service is free of charge for open-source projects. -.. note:: - - Appveyor has been removed in favour of GitHub Actions. - - We used to use `Travis `__ but this is no longer free of charge. - Sming performs the build and test logic is handled using scripts, which are intended to be easily portable to other CI services if necessary. Mostly batch scripts (.cmd) are used for Windows, and bash scripts (.sh) for GNU/Linux but @@ -47,10 +41,7 @@ Library CI support Sming libraries may be separately built and tested whether or not they are included as part of the Sming repository (or a fork). -There are two mechanisms available. - -GitHub Actions -~~~~~~~~~~~~~~ +There is currently only one supported mechanism available: GitHub Actions. The ``library.yml`` reusable workflow is provided, which takes care of these tasks: @@ -101,195 +92,3 @@ See https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a Note that the workflow must be available in the library's default branch, or it will not appear in the github web page. - - -Appveyor -~~~~~~~~ - -Appveyor may be configured to test a Sming library separately. Steps to enable: - -Add project to appveyor account - ``Projects`` -> ``New Project`` and select from list - -Set ``Custom Configuration`` - to https://raw.githubusercontent.com/SmingHub/Sming/develop/Tools/ci/library/appveyor.txt. - -Set ``Project URL slug`` - If the library under test already exists in the Sming framework then the test directory - MUST have the same name to ensure it gets picked up. - - For example, testing the ``Sming-jerryscript`` library requires this value to be set to ``jerryscript`` - to match the Sming library name. - Build logs should then report a warning ``Multiple matches found for Component 'jerryscript'``. - -Set sming fork/branch - By default builds use the main Sming ``develop`` branch. - If testing a library which requires changes to the framework, you'll need to use a fork - and add ``SMING_REPO`` and ``SMING_BRANCH`` environment variables to the project settings. - - Note that environment variables set here will override any values set in appveyor.txt. - -The provided default :source:`makefile ` -builds all applications within the library's ``samples`` directory. -If a test application is provided then that should be located in a ``test`` directory. -This is built for all architectures, and also executed for Host. - - -Build on your own 'cloud' -------------------------- - -Resources are limited to one concurrent build job per appveyor account. -Each build gets two virtual CPUs but they're not particular fast. -Network connectivity is, on the other hand, excellent! - -One very useful feature that appveyor provides is `Bring Your Own Cloud or Computer `__. -This allows the actual builds to be run on other hardware. - -Builds can have up to 5 concurrent jobs and as many CPUs as are available. -In addition, build images can be pre-installed with toolchains. -This can reduce total run times from 5+ hours to around 30 minutes. - - -Configuration -~~~~~~~~~~~~~ - -Full support requires a Windows server with Hyper-V, WSL2 and `Docker `__ installed. -Hyper-V is built into Windows 10/11 professional edition. -WSL2 should be available on all Windows versions. - -Linux/MacOS are supported but only for GNU/Linux images. - -Note that whilst Docker supports both Windows and Linux images, both cannot be used at the same time: -it is necessary to manually switch between Linux/Windows containers. -However, testing shows much better performance using Hyper-V for Windows builds. - -1. Add Docker build cloud for Linux builds: - - - Appveyor -> BYOC -> Add Cloud - - - Cloud Provider: Docker - - - Operating system: Windows - - - Base Image: ``Ubuntu 20.04 Minimal`` - - - Shell commands:: - - git clone https://github.com/SmingHub/Sming --branch develop --depth 1 /tmp/sming - pwsh /tmp/sming/Tools/Docker/appveyor/setup.ps1 - - - Image name: ``linux`` - - Execute commands as indicated in the resulting screen. - - Wait for the image to be built. - - The final stage updates the cloud information in your appveyor account. - Customise as follows: - - - Name - Change this so it contains only letters, numbers and dash (-). - Default names contain a space, e.g. ``COMPUTER Docker`` so change to ``COMPUTER-Docker`` - - - Custom Docker command arguments - Customise CPU resources, RAM usage, etc. For example:: - - --cpus=8 - - See https://docs.docker.com/engine/reference/commandline/run/. - - - Failover strategy - Default values will fail a job if no worker is available to service it. - The following settings are suggested:: - - Job start timeout: 60 - Provisioning attempts: 100 - - -2. Add Hyper-V build cloud for Windows builds: - -Same as (1) above except: - -- Cloud Provider: Hyper-V -- Base Image: ``Windows Server Core 2019 Minimal`` -- Image name: ``windows`` - -When complete, fix the build cloud name as previously, e.g. ``COMPUTER-HyperV``. -Also check CPU cores, RAM allocation, failover strategy. - - -3. Fix authorization token - -The above steps will also install the Appveyor Host Agent software on your computer. -This is the software which communicates with the Appveyor server and directs the build jobs. - -The authorization token used by the agent can be found in the registry: - -.. code-block:: text - - Computer\HKEY_LOCAL_MACHINE\SOFTWARE\AppVeyor\HostAgent - -Make sure that both clouds have the same token. - - -4. Configure BYOC images - - Select ``BYOC`` -> ``Images`` and amend mappings as follows: - - (1) - - - Image Name: ``Ubuntu2004`` - - OS Type: ``Linux`` - - Build cloud: "COMPUTER-Docker" (as configured above) - - (2) - - - Image Name: ``Visual Studio 2019`` - - OS Type: ``Windows`` - - Build cloud: "COMPUTER-HyperV" (as configured above) - - Now, when a build is started it should use your own server. - To revert back to normal operation change the ``Image Name`` fields in the entries. - It's not necessary to delete them: just add, say, "X" to the name so they're not recognised. - - - .. note:: - - Clouds may also be configured on a per-project basis by setting the ``APPVEYOR_BUILD_WORKER_CLOUD`` - environment variable to the appropriate cloud name. - - To get both Linux and Windows builds working concurrently using this approach would require a single - cloud to support dual images. - - -Rebuilding docker images -~~~~~~~~~~~~~~~~~~~~~~~~ - -Appveyor images are customised by pre-installing Sming build tools. -When these are updated images must be re-built. - -The easiest way to do this is using the provided dockerfiles:: - - cd $SMING_HOME/../Tools/Docker/appveyor - docker build --no-cache -t linux -f Dockerfile-Linux . - docker build --no-cache -t windows -f Dockerfile-Windows . - - -Custom images -------------- - -To use a Sming fork for building the image simply replace the repo URL and branch in the ``Shell Commands`` given above. - -These may also be passed to docker build as follows:: - - docker build -t linux-test -f Dockerfile-Linux --build-arg SMING_REPO=https://github.com/myrepo/Sming --build-arg SMING_BRANCH=feature/appveyor-revisions . - - -Issues ------- - -If you get error ``image not supported by cloud`` this probably means an image has been mapped to the wrong clould. -Goto Appveyor -> BYOC -> Images and update/delete the offending entries. - -If either cloud is shown as ``offline`` then check the authorization token (step 4 above). -It may be necessary to restart the ``Appveyor Host Agent`` service (via Windows service manager). diff --git a/docs/source/upgrading/5.1-5.2.rst b/docs/source/upgrading/5.1-5.2.rst index 1c18af0c26..739cc90521 100644 --- a/docs/source/upgrading/5.1-5.2.rst +++ b/docs/source/upgrading/5.1-5.2.rst @@ -111,3 +111,13 @@ The following macro definitions have been removed for esp8266: These related to the fixed system paramter block at the end of flash memory. With partitions this is relocatable so any code which depends on these will be wrong. + + +**CsvReader library** + +The :cpp:type:`CsvReader` class has been moved out of ``Core/Data`` and into :library:`CsvReader` +which has additional capabilities. Changes to existing code: + +- Add ``CsvReader`` to your project's :cpp:envvar:`COMPONENT_DEPENDS` +- Change ``#include `` to ``#include `` +- Change ``CsvReader`` class to :cpp:class:`CSV::Reader` diff --git a/samples/Basic_ProgMem/app/application.cpp b/samples/Basic_ProgMem/app/application.cpp index abdc5d24f4..8bccf27b0d 100644 --- a/samples/Basic_ProgMem/app/application.cpp +++ b/samples/Basic_ProgMem/app/application.cpp @@ -119,6 +119,6 @@ void init() Serial.println("> 0x3FFE8000 ~ 0x3FFFBFFF - User data RAM, 80kb. Available to applications."); Serial.println("> 0x40200000 ~ ... - SPI Flash."); - Serial << "> demoRam array address: 0x" << String(uint32_t(demoRam), HEX) << " is in the RAM" << endl; - Serial << "> demoPgm array address: 0x" << String(uint32_t(demoPgm), HEX) << " is in the Flash" << endl; + Serial << "> demoRam array address: 0x" << String(uintptr_t(demoRam), HEX) << " is in the RAM" << endl; + Serial << "> demoPgm array address: 0x" << String(uintptr_t(demoPgm), HEX) << " is in the Flash" << endl; } diff --git a/samples/Basic_Templates/app/CsvTemplate.h b/samples/Basic_Templates/app/CsvTemplate.h index b29b4ae349..cdf56fdd8a 100644 --- a/samples/Basic_Templates/app/CsvTemplate.h +++ b/samples/Basic_Templates/app/CsvTemplate.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include /** @@ -35,5 +35,5 @@ class CsvTemplate : public SectionTemplate } private: - CsvReader csv; + CSV::Reader csv; }; diff --git a/samples/Basic_Templates/app/application.cpp b/samples/Basic_Templates/app/application.cpp index efca95a384..a2bbae2d40 100644 --- a/samples/Basic_Templates/app/application.cpp +++ b/samples/Basic_Templates/app/application.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include "CsvTemplate.h" namespace @@ -51,7 +50,7 @@ void printCars() void printClassics(const FlashString& templateSource, Format::Formatter& formatter) { // The CSV data source - CsvReader csv(new FileStream(Filename::classics_csv)); + CSV::Reader csv(new FileStream(Filename::classics_csv)); // Use a regular SectionTemplate class to process the template SectionTemplate tmpl(new FSTR::Stream(templateSource)); diff --git a/samples/Basic_Templates/component.mk b/samples/Basic_Templates/component.mk index 092ca88129..bcb5ca8f81 100644 --- a/samples/Basic_Templates/component.mk +++ b/samples/Basic_Templates/component.mk @@ -1,3 +1,4 @@ +COMPONENT_DEPENDS := CsvReader HWCONFIG := basic_templates DISABLE_NETWORK := 1 diff --git a/tests/HostTests/modules/CStringArray.cpp b/tests/HostTests/modules/CStringArray.cpp index 61c8394099..bb640bf83f 100644 --- a/tests/HostTests/modules/CStringArray.cpp +++ b/tests/HostTests/modules/CStringArray.cpp @@ -24,6 +24,7 @@ class CStringArrayTest : public TestGroup "b\0" "c\0" "d\0"); + DEFINE_FSTR_LOCAL(FS_BasicJoined, "a,b,c,d") TEST_CASE("Empty construction") { @@ -231,6 +232,31 @@ class CStringArrayTest : public TestGroup csa.add(F("test\0again")); REQUIRE_EQ(csa.join("}+{"), "a}+{}+{test}+{again"); REQUIRE_EQ(csa.join(nullptr), "atestagain"); + + csa = FS_Basic; + REQUIRE_EQ(csa.join(), FS_BasicJoined); + } + + TEST_CASE("release") + { + CStringArray csa(FS_Basic); + csa += FS_Basic; // Allocate > SSO + Serial << csa.join() << endl; + auto cstrWant = csa.c_str(); + String s = csa.release(); + REQUIRE(!csa); + REQUIRE(s.c_str() == cstrWant); + + REQUIRE(s == String(FS_Basic) + FS_Basic); + + csa = std::move(s); + REQUIRE(csa == String(FS_Basic) + FS_Basic); + + String js; + js += FS_BasicJoined; + js += ','; + js += FS_BasicJoined; + REQUIRE(csa.join() == js); } } }; diff --git a/tests/HostTests/modules/Clocks.cpp b/tests/HostTests/modules/Clocks.cpp index b6c78fc775..b16097a04a 100644 --- a/tests/HostTests/modules/Clocks.cpp +++ b/tests/HostTests/modules/Clocks.cpp @@ -50,7 +50,7 @@ template class ClockTestTemplate : public TestG // Run for a second or two and check timer ticks correspond approximately with system clock constexpr uint64_t maxDuration = Clock::maxTicks().template as() - 5000ULL; - constexpr uint32_t duration = std::min(2000000ULL, maxDuration); + constexpr uint32_t duration = std::min(uint64_t(2000000ULL), maxDuration); auto startTime = system_get_time(); startTicks = Clock::ticks(); uint32_t time; diff --git a/tests/HostTests/modules/Serial.cpp b/tests/HostTests/modules/Serial.cpp index 069e98e22a..544f1f6bf2 100644 --- a/tests/HostTests/modules/Serial.cpp +++ b/tests/HostTests/modules/Serial.cpp @@ -41,7 +41,7 @@ class SerialTest : public TestGroup String compareBuffer; String readBuffer; for(unsigned i = 0; i < 10; ++i) { - m_printf("txfree = %u\n", txbuf.getFreeSpace()); + Serial << _F("txfree = ") << txbuf.getFreeSpace() << endl; for(char c = 'a'; c <= 'z'; ++c) { if(txbuf.getFreeSpace() < 10) { readBuffer += read(); diff --git a/tests/HostTests/modules/String.cpp b/tests/HostTests/modules/String.cpp index 8c48e8e5e5..b453142c27 100644 --- a/tests/HostTests/modules/String.cpp +++ b/tests/HostTests/modules/String.cpp @@ -15,6 +15,7 @@ class StringTest : public TestGroup nonTemplateTest(); testString(); + testMove(); testMakeHexString(); } @@ -154,17 +155,62 @@ class StringTest : public TestGroup } } + void testMove() + { + DEFINE_FSTR_LOCAL(shortText, "Not long") + DEFINE_FSTR_LOCAL(longText, "Greater than SSO buffer length") + + TEST_CASE("Move into unassigned string") + { + // Normal move + String s1 = longText; + String s2 = std::move(s1); + REQUIRE(!s1); + REQUIRE(s2.length() == longText.length()); + } + + TEST_CASE("Move between allocated strings of same length") + { + String s1 = longText; + auto cstrWant = s1.c_str(); + String s2 = std::move(s1); + REQUIRE(s2.c_str() == cstrWant); + } + + TEST_CASE("Move to allocated string of shorter length") + { + String s1 = longText; + String s2 = shortText; + auto cstrWant = s1.c_str(); + s2 = std::move(s1); + REQUIRE(s2.c_str() == cstrWant); + } + + TEST_CASE("Move to allocated string of longer length") + { + String s1 = longText; + String s2; + auto cstrWant = s1.c_str(); + s1 = ""; // Buffer remains allocated + s2 = std::move(s1); + REQUIRE(s2.c_str() == cstrWant); + } + } + void testMakeHexString() { - uint8_t hwaddr[] = {0xaa, 0xbb, 0xcc, 0xdd, 0x12, 0x55, 0x00}; - REQUIRE(makeHexString(nullptr, 6) == String::empty); - REQUIRE(makeHexString(hwaddr, 0) == String::empty); - REQUIRE(makeHexString(hwaddr, 6) == F("aabbccdd1255")); - REQUIRE(makeHexString(hwaddr, 6, ':') == F("aa:bb:cc:dd:12:55")); - REQUIRE(makeHexString(hwaddr, 7) == F("aabbccdd125500")); - REQUIRE(makeHexString(hwaddr, 7, ':') == F("aa:bb:cc:dd:12:55:00")); - REQUIRE(makeHexString(hwaddr, 1, ':') == F("aa")); - REQUIRE(makeHexString(hwaddr, 0, ':') == String::empty); + TEST_CASE("makeHexString") + { + uint8_t hwaddr[] = {0xaa, 0xbb, 0xcc, 0xdd, 0x12, 0x55, 0x00}; + REQUIRE(makeHexString(nullptr, 6) == String::empty); + REQUIRE(makeHexString(hwaddr, 0) == String::empty); + REQUIRE(makeHexString(hwaddr, 6) == F("aabbccdd1255")); + REQUIRE(makeHexString(hwaddr, 6, ':') == F("aa:bb:cc:dd:12:55")); + REQUIRE(makeHexString(hwaddr, 7) == F("aabbccdd125500")); + REQUIRE(makeHexString(hwaddr, 7, ':') == F("aa:bb:cc:dd:12:55:00")); + REQUIRE(makeHexString(hwaddr, 1, ':') == F("aa")); + REQUIRE(makeHexString(hwaddr, 0, ':') == String::empty); + } } }; diff --git a/tests/HostTests/modules/TemplateStream.cpp b/tests/HostTests/modules/TemplateStream.cpp index 66f1a6c9bc..36c725dd5a 100644 --- a/tests/HostTests/modules/TemplateStream.cpp +++ b/tests/HostTests/modules/TemplateStream.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #ifdef ARCH_HOST #include @@ -23,12 +22,6 @@ DEFINE_FSTR_LOCAL(template3_1, "Document Title