diff --git a/.gitignore b/.gitignore index b15779b9b5..f23638e90c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ tools/sdk/ld/eagle.app.v6.common.ld *.gch boards.local.txt +platform.local.txt *.gcov *.gcno diff --git a/.travis.yml b/.travis.yml index b3c39d2ee9..e2999f7a66 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,8 +15,8 @@ matrix: - BUILD_TYPE=platformio - env: - BUILD_TYPE=docs - - env: - - BUILD_TYPE=package +# - env: +# - BUILD_TYPE=package - env: - BUILD_TYPE=host_tests - env: @@ -40,28 +40,13 @@ install: script: - $TRAVIS_BUILD_DIR/tests/common.sh -deploy: - provider: releases - prerelease: true - skip_cleanup: true - api_key: - secure: A4FBmqyhlzy33oPeZVolg2Q/A3ZcJ3WnRQqQJ3NAPy+qGM5xcboOYtwcLL9vKaHZGfUB7lUP9QVZFGou1Wrmo9DnPvAoe3+XvCaDRGzVMxeIpu7UStbBD4Knbh98tlbMvZCXYRlT4VcusI9bMLK6UWw4sMdPislBh2FEfglTiag= - file_glob: true - file: - - package/versions/$TRAVIS_TAG/esp8266-$TRAVIS_TAG.zip - - package/versions/$TRAVIS_TAG/package_esp8266com_index.json - on: - repo: esp8266/Arduino - tags: true - condition: "$BUILD_TYPE = package" - notifications: email: on_success: change on_failure: change - webhooks: - urls: - - secure: "dnSY+KA7NK+KD+Z71copmANDUsyVePrZ0iXvXxmqMEQv+lp3j2Z87G5pHn7j0WNcNZrejJqOdbElJ9Q4QESRaAYxTR7cA6ameJeEKHiFJrQtN/4abvoXb9E1CxpL8aNON/xgnqCk+fycOK3nbWWXlJBodzBm7KN64vrcHO7et+M=" - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: false # default: false +# webhooks: +# urls: +# - https://webhooks.gitter.im/e/ +# on_success: change # options: [always|never|change] default: always +# on_failure: always # options: [always|never|change] default: always +# on_start: false # default: false diff --git a/README.md b/README.md index d67b4d683f..0ea456569e 100644 --- a/README.md +++ b/README.md @@ -1,121 +1,17 @@ -Arduino core for ESP8266 WiFi chip -=========================================== - -This project brings support for ESP8266 chip to the Arduino environment. It lets you write sketches using familiar Arduino functions and libraries, and run them directly on ESP8266, no external microcontroller required. - -ESP8266 Arduino core comes with libraries to communicate over WiFi using TCP and UDP, set up HTTP, mDNS, SSDP, and DNS servers, do OTA updates, use a file system in flash memory, work with SD cards, servos, SPI and I2C peripherals. - -# Contents -- Installing options: - - [Using Boards Manager](#installing-with-boards-manager) - - [Using git version](#using-git-version) - - [Using PlatformIO](#using-platformio) - - [Building with make](#building-with-make) -- [Documentation](#documentation) -- [Issues and support](#issues-and-support) -- [Contributing](#contributing) -- [License and credits](#license-and-credits) - -### Installing with Boards Manager - -Starting with 1.6.4, Arduino allows installation of third-party platform packages using Boards Manager. We have packages available for Windows, Mac OS, and Linux (32 and 64 bit). - -- Install the current upstream Arduino IDE at the 1.8 level or later. The current version is at the [Arduino website](http://www.arduino.cc/en/main/software). -- Start Arduino and open Preferences window. -- Enter ```http://arduino.esp8266.com/stable/package_esp8266com_index.json``` into *Additional Board Manager URLs* field. You can add multiple URLs, separating them with commas. -- Open Boards Manager from Tools > Board menu and install *esp8266* platform (and don't forget to select your ESP8266 board from Tools > Board menu after installation). - -#### Latest release [![Latest release](https://img.shields.io/github/release/esp8266/Arduino.svg)](https://github.com/esp8266/Arduino/releases/latest/) -Boards manager link: `http://arduino.esp8266.com/stable/package_esp8266com_index.json` - -Documentation: [https://arduino-esp8266.readthedocs.io/en/2.4.1/](https://arduino-esp8266.readthedocs.io/en/2.4.1/) - -### Using git version -[![Linux build status](https://travis-ci.org/esp8266/Arduino.svg)](https://travis-ci.org/esp8266/Arduino) - -- Install Arduino 1.8.2 from the [Arduino website](http://www.arduino.cc/en/main/software). -- Go to Arduino directory -- Clone this repository into hardware/esp8266com/esp8266 directory (or clone it elsewhere and create a symlink) -```bash -cd hardware -mkdir esp8266com -cd esp8266com -git clone https://github.com/esp8266/Arduino.git esp8266 -``` -- Download binary tools (you need Python 2.7) -```bash -cd esp8266/tools -python get.py -``` -- Restart Arduino - -### Using PlatformIO - -[PlatformIO](http://platformio.org?utm_source=github&utm_medium=arduino-esp8266) is an open source ecosystem for IoT -development with cross platform build system, library manager and full support -for Espressif (ESP8266) development. It works on the popular host OS: macOS, Windows, -Linux 32/64, Linux ARM (like Raspberry Pi, BeagleBone, CubieBoard). - -- [What is PlatformIO?](http://docs.platformio.org/en/latest/what-is-platformio.html?utm_source=github&utm_medium=arduino-esp8266) -- [PlatformIO IDE](http://platformio.org/platformio-ide?utm_source=github&utm_medium=arduino-esp8266) -- [PlatformIO Core](http://docs.platformio.org/en/latest/core.html?utm_source=github&utm_medium=arduino-esp8266) (command line tool) -- [Advanced usage](http://docs.platformio.org/en/latest/platforms/espressif8266.html?utm_source=github&utm_medium=arduino-esp8266) - - custom settings, uploading to SPIFFS, Over-the-Air (OTA), staging version -- [Integration with Cloud and Standalone IDEs](http://docs.platformio.org/en/latest/ide.html?utm_source=github&utm_medium=arduino-esp8266) - - Cloud9, Codeanywhere, Eclipse Che (Codenvy), Atom, CLion, Eclipse, Emacs, NetBeans, Qt Creator, Sublime Text, VIM, Visual Studio, and VSCode -- [Project Examples](http://docs.platformio.org/en/latest/platforms/espressif8266.html?utm_source=github&utm_medium=arduino-esp8266#examples) - -### Building with make - -[makeEspArduino](https://github.com/plerup/makeEspArduino) is a generic makefile for any ESP8266 Arduino project. -Using make instead of the Arduino IDE makes it easier to do automated and production builds. - -### Documentation - -Documentation for latest development version: https://arduino-esp8266.readthedocs.io/en/latest/ - -### Issues and support ### - -[ESP8266 Community Forum](http://www.esp8266.com/u/arduinoanswers) is a well established community for questions and answers about Arduino for ESP8266. - -If you find this forum useful, please consider supporting it with a donation.
-[![Donate](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.com/webscr?cmd=_s-xclick&hosted_button_id=4M56YCWV6PX66) - -If you encounter an issue which you think is a bug in the ESP8266 Arduino Core or the associated libraries, you are welcome to submit it here on Github: https://github.com/esp8266/Arduino/issues. - -Please provide as much context as possible: - -- ESP8266 Arduino core version which you are using (you can check it in Boards Manager) -- your sketch code; please wrap it into a code block, see [Github markdown manual](https://help.github.com/articles/basic-writing-and-formatting-syntax/#quoting-code) -- when encountering an issue which happens at run time, attach serial output. Wrap it into a code block, just like the code. -- for issues which happen at compile time, enable verbose compiler output in the IDE preferences, and attach that output (also inside a code block) -- ESP8266 development board model -- IDE settings (board choich, flash size) - -### Contributing - -For minor fixes of code and documentation, please go ahead and submit a pull request. - -Check out the list of issues which are easy to fix — [easy issues for 2.5.0](https://github.com/esp8266/Arduino/issues?q=is%3Aopen+is%3Aissue+milestone%3A2.5.0+label%3A%22level%3A+easy%22). Working on them is a great way to move the project forward. - -Larger changes (rewriting parts of existing code from scratch, adding new functions to the core, adding new libraries) should generally be discussed by opening an issue first. - -Feature branches with lots of small commits (especially titled "oops", "fix typo", "forgot to add file", etc.) should be squashed before opening a pull request. At the same time, please refrain from putting multiple unrelated changes into a single pull request. - -### License and credits ### - -Arduino IDE is developed and maintained by the Arduino team. The IDE is licensed under GPL. - -ESP8266 core includes an xtensa gcc toolchain, which is also under GPL. - -Esptool written by Christian Klippel is licensed under GPLv2, currently maintained by Ivan Grokhotkov: https://github.com/igrr/esptool-ck. - -Espressif SDK included in this build is under Espressif MIT License. - -ESP8266 core files are licensed under LGPL. - -[SPI Flash File System (SPIFFS)](https://github.com/pellepl/spiffs) written by Peter Andersson is used in this project. It is distributed under MIT license. - -[umm_malloc](https://github.com/rhempel/umm_malloc) memory management library written by Ralph Hempel is used in this project. It is distributed under MIT license. - -[axTLS](http://axtls.sourceforge.net/) library written by Cameron Rich, built from https://github.com/igrr/axtls-8266, is used in this project. It is distributed under [BSD license](https://github.com/igrr/axtls-8266/blob/master/LICENSE). +# Arduino core for ESP8266 WiFi chip +[![Build Status](https://travis-ci.org/Adam5Wu/Arduino-esp8266.svg?branch=adam5wu/master)](https://travis-ci.org/Adam5Wu/Arduino-esp8266) +[![GitHub issues](https://img.shields.io/github/issues/Adam5Wu/Arduino-esp8266.svg)](https://github.com/Adam5Wu/Arduino-esp8266/issues) +[![GitHub forks](https://img.shields.io/github/forks/Adam5Wu/Arduino-esp8266.svg)](https://github.com/Adam5Wu/Arduino-esp8266/network) +[![License](https://img.shields.io/github/license/Adam5Wu/Arduino-esp8266.svg)](./LICENSE) + +Arduino core for ESP8266 WiFi chip. +Altered mainly for the following new features: +- vFAT file system for internal flash +- BearSSL library that works with [ESPAsyncTCP fork](https://github.com/Adam5Wu/ESPAsyncTCP) + +* [Upstream Project](https://github.com/esp8266/Arduino) +* [Modifications of this fork](MODIFICATIONS.md) +* Potentially interesting: + - [ESPvFATFS](https://github.com/Adam5Wu/ESPVFATFS) + - [BearSSL-esp8266 fork](https://github.com/Adam5Wu/bearssl-esp8266) + - [ESPAsyncTCP fork](https://github.com/Adam5Wu/ESPAsyncTCP) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index c8969691b8..10549b44a8 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -125,7 +125,7 @@ uint64_t EspClass::deepSleepMax() bool EspClass::rtcUserMemoryRead(uint32_t offset, uint32_t *data, size_t size) { - if (size + offset > 512) { + if (size + offset*4 > 512) { return false; } else { return system_rtc_mem_read(64 + offset, data, size); @@ -134,7 +134,7 @@ bool EspClass::rtcUserMemoryRead(uint32_t offset, uint32_t *data, size_t size) bool EspClass::rtcUserMemoryWrite(uint32_t offset, uint32_t *data, size_t size) { - if (size + offset > 512) { + if (size + offset*4 > 512) { return false; } else { return system_rtc_mem_write(64 + offset, data, size); diff --git a/cores/esp8266/FS.cpp b/cores/esp8266/FS.cpp index 6ae11e1782..d46984f109 100644 --- a/cores/esp8266/FS.cpp +++ b/cores/esp8266/FS.cpp @@ -23,261 +23,294 @@ using namespace fs; -static bool sflags(const char* mode, OpenMode& om, AccessMode& am); +static bool sflags(const char *mode, OpenMode& om, AccessMode& am); -size_t File::write(uint8_t c) { - if (!_p) - return 0; - - return _p->write(&c, 1); -} +// File size_t File::write(const uint8_t *buf, size_t size) { - if (!_p) - return 0; + if (!_file_impl) return 0; + return _file_impl->write(buf, size); +} - return _p->write(buf, size); +size_t File::read(uint8_t* buf, size_t size) { + if (!_file_impl) return -1; + return _file_impl->read(buf, size); } int File::available() { - if (!_p) - return false; - - return _p->size() - _p->position(); + if (!_file_impl) return false; + return _file_impl->size() - _file_impl->position(); } int File::read() { - if (!_p) - return -1; + uint8_t result; + if (read(&result, 1) != 1) { + return -1; + } + return result; +} - uint8_t result; - if (_p->read(&result, 1) != 1) { - return -1; - } +int File::peek() { + uint8_t result; + if (read(&result, 1) != 1) { + return -1; + } + seek(-1, SeekCur); + return result; +} - return result; +void File::flush() { + if (!_file_impl) return; + _file_impl->flush(); } -size_t File::read(uint8_t* buf, size_t size) { - if (!_p) - return -1; +bool File::seek(int32_t pos, SeekMode mode) { + if (!_file_impl) return false; + return _file_impl->seek(pos, mode); +} - return _p->read(buf, size); +bool File::truncate() { + if (!_file_impl) return false; + return _file_impl->truncate(); } -int File::peek() { - if (!_p) - return -1; +size_t File::size() const { + if (!_file_impl) return 0; + return _file_impl->size(); +} - size_t curPos = _p->position(); - int result = read(); - seek(curPos, SeekSet); - return result; +time_t File::mtime() const { + if (!_file_impl) { + time_t ret{0}; + return ret; + } + return _file_impl->mtime(); } -void File::flush() { - if (!_p) - return; +size_t File::position() const { + if (!_file_impl) return 0; + return _file_impl->position(); +} - _p->flush(); +const char *File::name() const { + if (!_file_impl) return nullptr; + return _file_impl->name(); } -bool File::seek(uint32_t pos, SeekMode mode) { - if (!_p) - return false; +File::operator bool() const { + return !!_file_impl; +} - return _p->seek(pos, mode); +void File::close() { + if (_file_impl) { + _file_impl->close(); + _file_impl = nullptr; + } } -size_t File::position() const { - if (!_p) - return 0; +bool File::remove() { + if (!_file_impl) return false; + auto __file_impl = std::move(_file_impl); + //_file_impl = nullptr; + return __file_impl->remove(); +} - return _p->position(); +bool File::rename(const char *pathTo) { + if (!_file_impl) return false; + auto __file_impl = std::move(_file_impl); + //_file_impl = nullptr; + return __file_impl->rename(pathTo); } -size_t File::size() const { - if (!_p) - return 0; +// Dir + +File Dir::openFile(const char *name, const char *mode) { + if (!_dir_impl) return File(); - return _p->size(); + OpenMode om; + AccessMode am; + if (!sflags(mode, om, am)) { + DEBUGV("Dir::openFile: invalid mode `%s`\n", mode); + return File(); + } + + return File(_dir_impl->openFile(name, om, am)); } -void File::close() { - if (_p) { - _p->close(); - _p = nullptr; - } +Dir Dir::openDir(const char *name, bool create) { + if (!_dir_impl) return Dir(); + return Dir(_dir_impl->openDir(name, create)); } -File::operator bool() const { - return !!_p; +bool Dir::exists(const char *name) const { + if (!_dir_impl) return false; + return _dir_impl->exists(name); } -const char* File::name() const { - if (!_p) - return nullptr; +bool Dir::isDir(const char *name) const { + if (!_dir_impl) return false; + return _dir_impl->isDir(name); +} - return _p->name(); +size_t Dir::size(const char *name) const { + if (!_dir_impl) return 0; + return _dir_impl->size(name); } -File Dir::openFile(const char* mode) { - if (!_impl) { - return File(); - } +time_t Dir::mtime(const char *name) const { + if (!_dir_impl) return 0; + return _dir_impl->mtime(name); +} - OpenMode om; - AccessMode am; - if (!sflags(mode, om, am)) { - DEBUGV("Dir::openFile: invalid mode `%s`\r\n", mode); - return File(); - } +bool Dir::remove(const char *name) { + if (!_dir_impl) return false; + return _dir_impl->remove(name); +} - return File(_impl->openFile(om, am)); +bool Dir::rename(const char *nameFrom, const char *nameTo) { + if (!_dir_impl) return false; + return _dir_impl->rename(nameFrom, nameTo); } -String Dir::fileName() { - if (!_impl) { - return String(); - } +bool Dir::next(bool reset) { + if (!_dir_impl) return false; + return _dir_impl->next(reset); +} - return _impl->fileName(); +const char *Dir::entryName() const { + if (!_dir_impl) return nullptr; + return _dir_impl->entryName(); } -size_t Dir::fileSize() { - if (!_impl) { - return 0; - } +size_t Dir::entrySize() const { + if (!_dir_impl) return 0; + return _dir_impl->entrySize(); +} - return _impl->fileSize(); +time_t Dir::entryMtime() const { + if (!_dir_impl) return 0; + return _dir_impl->entryMtime(); } -bool Dir::next() { - if (!_impl) { - return false; - } +bool Dir::isEntryDir() const { + if (!_dir_impl) return false; + return _dir_impl->isEntryDir(); +} - return _impl->next(); +time_t Dir::mtime() const { + if (!_dir_impl) return 0; + return _dir_impl->mtime(); } -bool FS::begin() { - if (!_impl) { - return false; - } - return _impl->begin(); +const char *Dir::name() const { + if (!_dir_impl) return nullptr; + return _dir_impl->name(); } -void FS::end() { - if (_impl) { - _impl->end(); - } +Dir::operator bool() const { + return !!_dir_impl; } -bool FS::format() { - if (!_impl) { - return false; - } - return _impl->format(); +// FS + +bool FS::begin() { + if (!_fs_impl) return false; + return _fs_impl->begin(); } -bool FS::info(FSInfo& info){ - if (!_impl) { - return false; - } - return _impl->info(info); +void FS::end() { + if (_fs_impl) { + _fs_impl->end(); + } } -File FS::open(const String& path, const char* mode) { - return open(path.c_str(), mode); +bool FS::format() { + if (!_fs_impl) return false; + return _fs_impl->format(); } -File FS::open(const char* path, const char* mode) { - if (!_impl) { - return File(); - } +bool FS::info(FSInfo& info) const { + if (!_fs_impl) return false; + return _fs_impl->info(info); +} - OpenMode om; - AccessMode am; - if (!sflags(mode, om, am)) { - DEBUGV("FS::open: invalid mode `%s`\r\n", mode); - return File(); - } +File FS::openFile(const char *path, const char *mode) { + if (!_fs_impl) return File(); - return File(_impl->open(path, om, am)); -} + OpenMode om; + AccessMode am; + if (!sflags(mode, om, am)) { + DEBUGV("FS::open: invalid mode `%s`\n", mode); + return File(); + } -bool FS::exists(const char* path) { - if (!_impl) { - return false; - } - return _impl->exists(path); + return File(_fs_impl->openFile(path, om, am)); } -bool FS::exists(const String& path) { - return exists(path.c_str()); +Dir FS::openDir(const char *path, bool create) { + if (!_fs_impl) return Dir(); + return Dir(_fs_impl->openDir(path, create)); } -Dir FS::openDir(const char* path) { - if (!_impl) { - return Dir(); - } - return Dir(_impl->openDir(path)); +bool FS::exists(const char *path) const { + if (!_fs_impl) return false; + return _fs_impl->exists(path); } -Dir FS::openDir(const String& path) { - return openDir(path.c_str()); +bool FS::isDir(const char *path) const { + if (!_fs_impl) return false; + return _fs_impl->isDir(path); } -bool FS::remove(const char* path) { - if (!_impl) { - return false; - } - return _impl->remove(path); +size_t FS::size(const char *path) const { + if (!_fs_impl) return false; + return _fs_impl->mtime(path); } -bool FS::remove(const String& path) { - return remove(path.c_str()); +time_t FS::mtime(const char *path) const { + if (!_fs_impl) return false; + return _fs_impl->mtime(path); } -bool FS::rename(const char* pathFrom, const char* pathTo) { - if (!_impl) { - return false; - } - return _impl->rename(pathFrom, pathTo); +bool FS::remove(const char *path) { + if (!_fs_impl) return false; + return _fs_impl->remove(path); } -bool FS::rename(const String& pathFrom, const String& pathTo) { - return rename(pathFrom.c_str(), pathTo.c_str()); +bool FS::rename(const char *pathFrom, const char *pathTo) { + if (!_fs_impl) return false; + return _fs_impl->rename(pathFrom, pathTo); } +// Utility functions -static bool sflags(const char* mode, OpenMode& om, AccessMode& am) { - switch (mode[0]) { - case 'r': - am = AM_READ; - om = OM_DEFAULT; - break; - case 'w': - am = AM_WRITE; - om = (OpenMode) (OM_CREATE | OM_TRUNCATE); - break; - case 'a': - am = AM_WRITE; - om = (OpenMode) (OM_CREATE | OM_APPEND); - break; - default: - return false; - } - switch(mode[1]) { - case '+': - am = (AccessMode) (AM_WRITE | AM_READ); - break; - case 0: - break; - default: - return false; - } - return true; +static bool sflags(const char *mode, OpenMode& om, AccessMode& am) { + switch (mode[0]) { + case 'r': + am = AM_READ; + om = OM_DEFAULT; + break; + case 'w': + am = AM_WRITE; + om = (OpenMode) (OM_CREATE | OM_TRUNCATE); + break; + case 'a': + am = AM_WRITE; + om = (OpenMode) (OM_CREATE | OM_APPEND); + break; + default: + return false; + } + switch(mode[1]) { + case '+': + am = (AccessMode) (AM_WRITE | AM_READ); + break; + case 0: + break; + default: + return false; + } + return true; } @@ -286,73 +319,82 @@ static bool sflags(const char* mode, OpenMode& om, AccessMode& am) { /* TODO: move these functions to public API: */ -File open(const char* path, const char* mode); -File open(String& path, const char* mode); +// Arduino legacy API compatibility +File open(const char *path, const char *mode); -Dir openDir(const char* path); -Dir openDir(String& path); +File openFile(const char *path, const char *mode); +File openFile(String& path, const char *mode); -template<> -bool mount(FS& fs, const char* mountPoint); -/* -*/ +Dir openDir(const char *path, bool create = false); +Dir openDir(String& path, bool create = false); +template<> +bool mount(FS& fs, const char *mountPoint); struct MountEntry { - FSImplPtr fs; - String path; - MountEntry* next; + FSImplPtr fs; + String path; + MountEntry* next; }; static MountEntry* s_mounted = nullptr; template<> -bool mount(FS& fs, const char* mountPoint) { - FSImplPtr p = fs._impl; - if (!p || !p->mount()) { - DEBUGV("FSImpl mount failed\r\n"); - return false; - } +bool mount(FS& fs, const char *mp) { + FSImplPtr p = fs._fs_impl; + if (!p || !p->mount()) { + DEBUGV("FSImpl mount failed\n"); + return false; + } - !make sure mountPoint has trailing '/' here + if (!mp || *mp != '/') { + DEBUGV("Invalid mount point\n"); + return false; + } - MountEntry* entry = new MountEntry; - entry->fs = p; - entry->path = mountPoint; - entry->next = s_mounted; - s_mounted = entry; - return true; + MountEntry* entry = new MountEntry; + entry->fs = p; + entry->path = mp; + entry->next = s_mounted; + s_mounted = entry; + return true; } /* - iterate over MountEntries and look for the ones which match the path + iterate over MountEntries and look for the ones which match the path */ -File open(const char* path, const char* mode) { - OpenMode om; - AccessMode am; - if (!sflags(mode, om, am)) { - DEBUGV("open: invalid mode `%s`\r\n", mode); - return File(); - } +File openFile(String const &path, const char *mode) { + for (MountEntry* entry = s_mounted; entry; entry = entry->next) { + size_t offset = entry->path.length(); + if (path.startsWith(entry->path)) { + File result = entry->fs->openFile(path.begin()+offset, mode); + if (result) return result; + } + } + return File(); +} - for (MountEntry* entry = s_mounted; entry; entry = entry->next) { - size_t offset = entry->path.length(); - if (strstr(path, entry->path.c_str())) { - File result = entry->fs->open(path + offset); - if (result) - return result; - } - } +Dir openDir(String const &path, bool create) { + for (MountEntry* entry = s_mounted; entry; entry = entry->next) { + size_t offset = entry->path.length(); + if (path.startsWith(entry->path)) { + Dir result = entry->fs->openDir(path.begin()+offset, create); + if (result) return result; + } + } + return Dir(); +} - return File(); +File openFile(const char *path, const char *mode) { + return FS::openFile(path, mode); } -File open(const String& path, const char* mode) { - return FS::open(path.c_str(), mode); +File open(const char *path, const char *mode) { + return FS::openFile(path, mode); } -Dir openDir(const String& path) { - return openDir(path.c_str()); +Dir openDir(const char *path, bool create) { + return FS::openDir(path.c_str(), create); } #endif diff --git a/cores/esp8266/FS.h b/cores/esp8266/FS.h index 79620f96c8..f8d897eb0e 100644 --- a/cores/esp8266/FS.h +++ b/cores/esp8266/FS.h @@ -37,96 +37,188 @@ class DirImpl; typedef std::shared_ptr DirImplPtr; template -bool mount(Tfs& fs, const char* mountPoint); +bool mount(Tfs& fs, const char *mountPoint); enum SeekMode { - SeekSet = 0, - SeekCur = 1, - SeekEnd = 2 + SeekSet = 0, + SeekCur = 1, + SeekEnd = 2 }; -class File : public Stream -{ +class FS; + +class File : public Stream { public: - File(FileImplPtr p = FileImplPtr()) : _p(p) {} - - // Print methods: - size_t write(uint8_t) override; - size_t write(const uint8_t *buf, size_t size) override; - - // Stream methods: - int available() override; - int read() override; - int peek() override; - void flush() override; - size_t readBytes(char *buffer, size_t length) override { - return read((uint8_t*)buffer, length); - } - size_t read(uint8_t* buf, size_t size); - bool seek(uint32_t pos, SeekMode mode); - bool seek(uint32_t pos) { - return seek(pos, SeekSet); - } - size_t position() const; - size_t size() const; - void close(); - operator bool() const; - const char* name() const; + File(FileImplPtr file_impl = FileImplPtr()) : _file_impl(file_impl) {} + + // Print methods: + size_t write(const uint8_t *buf, size_t size) override; + size_t write(uint8_t c) override + { return write(&c, 1); } + + size_t read(uint8_t* buf, size_t size); + size_t readBytes(char *buffer, size_t length) override + { return read((uint8_t*)buffer, length); } + + // Stream methods: + int available() override; + int read() override; + int peek() override; + void flush() override; + + bool seek(int32_t pos, SeekMode mode); + bool seek(int32_t pos) + { return seek(pos, SeekSet); } + bool truncate(); + bool truncate(int32_t pos) + { return seek(pos)? truncate() : false; } + + size_t size() const; + time_t mtime() const; + size_t position() const; + + const char *name() const; + operator bool() const; + + void close(); + bool remove(); + bool rename(const char *nameTo); + bool rename(String const &nameTo) + { return rename(nameTo.c_str()); } protected: - FileImplPtr _p; + FileImplPtr _file_impl; }; class Dir { public: - Dir(DirImplPtr impl = DirImplPtr()): _impl(impl) { } - - File openFile(const char* mode); - String fileName(); - size_t fileSize(); - bool next(); + Dir(DirImplPtr dir_impl = DirImplPtr()): _dir_impl(dir_impl) { } + + // Arduino legacy API compatibility + File openFile(const char *mode) + { return openEntryFile(mode); } + String fileName() + { return entryName(); } + size_t fileSize() + { return entrySize(); } + + File openFile(const char *name, const char *mode); + File openFile(String const &name, const char *mode) + { return openFile(name.c_str(), mode); } + + Dir openDir(const char *name, bool create = false); + Dir openDir(String const &name, bool create = false) + { return openDir(name.c_str(), create); } + + bool exists(const char *name) const; + bool exists(String const &name) const + { return exists(name.c_str()); } + + bool isDir(const char *name) const; + bool isDir(String const &name) const + { return isDir(name.c_str()); } + + size_t size(const char *name) const; + size_t size(String const &name) const + { return size(name.c_str()); } + + time_t mtime(const char *name) const; + time_t mtime(String const &name) const + { return mtime(name.c_str()); } + + bool remove(const char *name); + bool remove(String const &name) + { return remove(name.c_str()); } + + bool rename(const char *nameFrom, const char *nameTo); + bool rename(String const &nameFrom, String const &nameTo) + { return rename(nameFrom.c_str(), nameTo.c_str()); } + + bool next(bool reset = false); + + const char *entryName() const; + size_t entrySize() const; + time_t entryMtime() const; + bool isEntryDir() const; + + File openEntryFile(const char *mode) + { return openFile(entryName(), mode); } + Dir openEntryDir() + { return openDir(entryName()); } + bool removeEntry() + { return remove(entryName()); } + bool renameEntry(const char *nameTo) + { return rename(entryName(), nameTo); } + bool renameEntry(String const &nameTo) + { return renameEntry(nameTo.c_str()); } + + time_t mtime() const; + const char *name() const; + operator bool() const; protected: - DirImplPtr _impl; + DirImplPtr _dir_impl; }; struct FSInfo { - size_t totalBytes; - size_t usedBytes; - size_t blockSize; - size_t pageSize; - size_t maxOpenFiles; - size_t maxPathLength; + size_t totalBytes; + size_t usedBytes; + size_t blockSize; + size_t pageSize; + size_t maxOpenFiles; + size_t maxPathLength; }; -class FS -{ +class FS { public: - FS(FSImplPtr impl) : _impl(impl) { } + FS(FSImplPtr fs_impl) : _fs_impl(fs_impl) { } + + bool begin(); + void end(); + + bool format(); + bool info(FSInfo& info) const; + + // Arduino legacy API compatibility + File open(const char *path, const char *mode) + { return openFile(path, mode); } + File open(String const &path, const char *mode) + { return openFile(path.c_str(), mode); } + + File openFile(const char *path, const char *mode); + File openFile(String const &path, const char *mode) + { return openFile(path.c_str(), mode); } + + Dir openDir(const char *path, bool create = false); + Dir openDir(String const &path, bool create = false) + { return openDir(path.c_str(), create); } - bool begin(); - void end(); - - bool format(); - bool info(FSInfo& info); + bool exists(const char *path) const; + bool exists(String const &path) const + { return exists(path.c_str()); } - File open(const char* path, const char* mode); - File open(const String& path, const char* mode); + bool isDir(const char *path) const; + bool isDir(String const &path) const + { return isDir(path.c_str()); } - bool exists(const char* path); - bool exists(const String& path); + size_t size(const char *path) const; + size_t size(String const &path) const + { return size(path.c_str()); } - Dir openDir(const char* path); - Dir openDir(const String& path); + time_t mtime(const char *path) const; + time_t mtime(String const &path) const + { return mtime(path.c_str()); } - bool remove(const char* path); - bool remove(const String& path); + bool remove(const char *path); + bool remove(String const &path) + { return remove(path.c_str()); } - bool rename(const char* pathFrom, const char* pathTo); - bool rename(const String& pathFrom, const String& pathTo); + bool rename(const char *pathFrom, const char *pathTo); + bool rename(String const &pathFrom, String const &pathTo) + { return rename(pathFrom.c_str(), pathTo.c_str()); } protected: - FSImplPtr _impl; + FSImplPtr _fs_impl; }; } // namespace fs diff --git a/cores/esp8266/FSImpl.h b/cores/esp8266/FSImpl.h index e5694b5f68..fbce5cab88 100644 --- a/cores/esp8266/FSImpl.h +++ b/cores/esp8266/FSImpl.h @@ -25,53 +25,84 @@ namespace fs { +class FSImpl; + class FileImpl { public: - virtual ~FileImpl() { } - virtual size_t write(const uint8_t *buf, size_t size) = 0; - virtual size_t read(uint8_t* buf, size_t size) = 0; - virtual void flush() = 0; - virtual bool seek(uint32_t pos, SeekMode mode) = 0; - virtual size_t position() const = 0; - virtual size_t size() const = 0; - virtual void close() = 0; - virtual const char* name() const = 0; + virtual ~FileImpl() { } + virtual size_t write(const uint8_t *buf, size_t size) = 0; + virtual size_t read(uint8_t* buf, size_t size) = 0; + virtual void flush() = 0; + virtual bool seek(uint32_t pos, SeekMode mode) = 0; + virtual bool truncate() = 0; + + virtual size_t position() const = 0; + virtual size_t size() const = 0; + virtual const char* name() const = 0; + virtual time_t mtime() const = 0; + virtual bool remove() = 0; + virtual bool rename(const char *pathTo) = 0; + + virtual void close() = 0; }; enum OpenMode { - OM_DEFAULT = 0, - OM_CREATE = 1, - OM_APPEND = 2, - OM_TRUNCATE = 4 + OM_DEFAULT = 0, + OM_CREATE = 1, + OM_APPEND = 2, + OM_TRUNCATE = 4 }; enum AccessMode { - AM_READ = 1, - AM_WRITE = 2, - AM_RW = AM_READ | AM_WRITE + AM_READ = 1, + AM_WRITE = 2, + AM_RW = AM_READ | AM_WRITE }; class DirImpl { public: - virtual ~DirImpl() { } - virtual FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) = 0; - virtual const char* fileName() = 0; - virtual size_t fileSize() = 0; - virtual bool next() = 0; + virtual ~DirImpl() { } + virtual FileImplPtr openFile(const char* name, OpenMode openMode, + AccessMode accessMode) = 0; + virtual DirImplPtr openDir(const char* name, bool create) = 0; + virtual bool exists(const char* path) const = 0; + virtual bool isDir(const char* name) const = 0; + virtual size_t size(const char* name) const = 0; + virtual time_t mtime(const char* name) const = 0; + virtual bool remove(const char* name) = 0; + virtual bool rename(const char *nameFrom, const char *nameTo) = 0; + + virtual bool next(bool reset) = 0; + virtual const char* entryName() const = 0; + virtual size_t entrySize() const = 0; + virtual time_t entryMtime() const = 0; + virtual bool isEntryDir() const = 0; + + virtual FileImplPtr openEntryFile(OpenMode openMode, + AccessMode accessMode) = 0; + virtual DirImplPtr openEntryDir() = 0; + virtual bool removeEntry() = 0; + virtual bool renameEntry(const char *pathTo) = 0; + + virtual time_t mtime() const = 0; + virtual const char* name() const = 0; }; class FSImpl { public: - virtual bool begin() = 0; - virtual void end() = 0; - virtual bool format() = 0; - virtual bool info(FSInfo& info) = 0; - virtual FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) = 0; - virtual bool exists(const char* path) = 0; - virtual DirImplPtr openDir(const char* path) = 0; - virtual bool rename(const char* pathFrom, const char* pathTo) = 0; - virtual bool remove(const char* path) = 0; - + virtual bool begin() = 0; + virtual void end() = 0; + virtual bool format() = 0; + virtual bool info(FSInfo& info) const = 0; + virtual bool exists(const char* path) const = 0; + virtual bool isDir(const char* path) const = 0; + virtual size_t size(const char* path) const = 0; + virtual time_t mtime(const char* path) const = 0; + virtual FileImplPtr openFile(const char* path, OpenMode openMode, + AccessMode accessMode) = 0; + virtual DirImplPtr openDir(const char* path, bool create) = 0; + virtual bool remove(const char* path) = 0; + virtual bool rename(const char* pathFrom, const char* pathTo) = 0; }; } // namespace fs diff --git a/cores/esp8266/StreamString.cpp b/cores/esp8266/StreamString.cpp index 7ebf11d0e2..5ad8402d4b 100644 --- a/cores/esp8266/StreamString.cpp +++ b/cores/esp8266/StreamString.cpp @@ -23,14 +23,24 @@ #include #include "StreamString.h" +#include + +size_t PrintString::write(const uint8_t *data, size_t size) { + if(size && data) { + if(concat((const char *)data, size)) + return size; + } + return 0; +} + +size_t PrintString::write(uint8_t data) { + return concat((char) data); +} + size_t StreamString::write(const uint8_t *data, size_t size) { if(size && data) { - if(reserve(length() + size + 1)) { - memcpy((void *) (buffer + len), (const void *) data, size); - len += size; - *(buffer + len) = 0x00; // add null for string end + if(concat((const char *)data, size)) return size; - } } return 0; } @@ -39,24 +49,27 @@ size_t StreamString::write(uint8_t data) { return concat((char) data); } +size_t StreamString::readBytes(char *buffer, size_t length) { + size_t readlen = std::min(length, (size_t)available()); + memcpy(buffer, begin()+_offset, readlen); + _offset += readlen; + return readlen; +} + int StreamString::available() { - return length(); + return length() - _offset; } int StreamString::read() { - if(length()) { - char c = charAt(0); - remove(0, 1); - return c; - + if(available()) { + return charAt(_offset++); } return -1; } int StreamString::peek() { - if(length()) { - char c = charAt(0); - return c; + if(available()) { + return charAt(_offset); } return -1; } diff --git a/cores/esp8266/StreamString.h b/cores/esp8266/StreamString.h index 1fedc18de0..9a4405dbe2 100644 --- a/cores/esp8266/StreamString.h +++ b/cores/esp8266/StreamString.h @@ -1,39 +1,68 @@ -/** - StreamString.h - - Copyright (c) 2015 Markus Sattler. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -*/ - -#ifndef STREAMSTRING_H_ -#define STREAMSTRING_H_ - - -class StreamString: public Stream, public String { -public: - size_t write(const uint8_t *buffer, size_t size) override; - size_t write(uint8_t data) override; - - int available() override; - int read() override; - int peek() override; - void flush() override; -}; - - -#endif /* STREAMSTRING_H_ */ +/** + StreamString.h + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef STREAMSTRING_H_ +#define STREAMSTRING_H_ + +#include +#include +#include + +#include + +class PrintString: public String, public Print { + public: + PrintString(void) {} + PrintString(const __FlashStringHelper *str) : String(str) {} +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + PrintString(String &&rval) : String(std::move(rval)) {} +#endif + + size_t write(const uint8_t *buffer, size_t size) override; + size_t write(uint8_t data) override; +}; + +class StreamString: public Stream, public String { + protected: + size_t _offset = 0; + public: + StreamString(void) {} + StreamString(const __FlashStringHelper *str) : String(str) {} +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + StreamString(String &&rval) : String(std::move(rval)) {} +#endif + + size_t write(const uint8_t *buffer, size_t size) override; + size_t write(uint8_t data) override; + + size_t readBytes(char *buffer, size_t length) override; + + int available() override; + int read() override; + int peek() override; + void flush() override; + + void reset() { _offset = 0; } +}; + + +#endif /* STREAMSTRING_H_ */ diff --git a/cores/esp8266/WCharacter.h b/cores/esp8266/WCharacter.h index f37ddb71c3..0d3fee0edf 100644 --- a/cores/esp8266/WCharacter.h +++ b/cores/esp8266/WCharacter.h @@ -21,8 +21,8 @@ #define Character_h #include -#define isascii(__c) ((unsigned)(__c)<=0177) -#define toascii(__c) ((__c)&0177) +//#define isascii(__c) ((unsigned)(__c)<=0177) +//#define toascii(__c) ((__c)&0177) // WCharacter.h prototypes inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index c81b594d6c..8e780e7b89 100644 --- a/cores/esp8266/WString.cpp +++ b/cores/esp8266/WString.cpp @@ -5,6 +5,7 @@ Copyright 2011, Paul Stoffregen, paul@pjrc.com Modified by Ivan Grokhotkov, 2014 - esp8266 support Modified by Michael C. Miller, 2015 - esp8266 progmem support + Modified by Zhenyu Wu for VFATFS, 2017.01 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -22,98 +23,87 @@ */ #include +#include #include "WString.h" #include "stdlib_noniso.h" +String const String::EMPTY(""); + /*********************************************/ /* Constructors */ /*********************************************/ -String::String(const char *cstr) { - init(); - if(cstr) - copy(cstr, strlen(cstr)); +String::String(const char *cstr, size_t len) { + init(); + if(cstr) + copy(cstr, len? len: strlen(cstr)); } -String::String(const String &value) { - init(); - *this = value; +String::String(String const &value) { + init(); + *this = value; } -String::String(const __FlashStringHelper *pstr) { - init(); - *this = pstr; // see operator = +String::String(const __FlashStringHelper *pstr, size_t len) { + init(); + if (pstr) + copy(pstr, len? len: strlen_P((PGM_P)pstr)); } #ifdef __GXX_EXPERIMENTAL_CXX0X__ String::String(String &&rval) { - init(); - move(rval); + init(); + move(rval); } String::String(StringSumHelper &&rval) { - init(); - move(rval); + init(); + move(rval); } #endif -String::String(char c) { - init(); - char buf[2]; - buf[0] = c; - buf[1] = 0; - *this = buf; +String::String(char c, size_t count) { + init(); + concat(c, count); } String::String(unsigned char value, unsigned char base) { - init(); - char buf[1 + 8 * sizeof(unsigned char)]; - utoa(value, buf, base); - *this = buf; + init(); + concat(value, base); } String::String(int value, unsigned char base) { - init(); - char buf[2 + 8 * sizeof(int)]; - itoa(value, buf, base); - *this = buf; + init(); + concat(value, base); } String::String(unsigned int value, unsigned char base) { - init(); - char buf[1 + 8 * sizeof(unsigned int)]; - utoa(value, buf, base); - *this = buf; + init(); + concat(value, base); } String::String(long value, unsigned char base) { - init(); - char buf[2 + 8 * sizeof(long)]; - ltoa(value, buf, base); - *this = buf; + init(); + concat(value, base); } String::String(unsigned long value, unsigned char base) { - init(); - char buf[1 + 8 * sizeof(unsigned long)]; - ultoa(value, buf, base); - *this = buf; + init(); + concat(value, base); } String::String(float value, unsigned char decimalPlaces) { - init(); - char buf[33]; - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); + init(); + concat(value, decimalPlaces); } String::String(double value, unsigned char decimalPlaces) { - init(); - char buf[33]; - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); + init(); + concat(value, decimalPlaces); } String::~String() { - invalidate(); + invalidate(); } // /*********************************************/ @@ -121,42 +111,33 @@ String::~String() { // /*********************************************/ inline void String::init(void) { - buffer = NULL; - capacity = 0; - len = 0; + buffer = NULL; + capacity = 0; + len = 0; } void String::invalidate(void) { - if(buffer) - free(buffer); - init(); + if(buffer) { + free(buffer); + init(); + } } unsigned char String::reserve(unsigned int size) { - if(buffer && capacity >= size) - return 1; - if(changeBuffer(size)) { - if(len == 0) - buffer[0] = 0; - return 1; - } - return 0; + if(buffer && capacity >= size) + return 1; + return changeBuffer(size); } unsigned char String::changeBuffer(unsigned int maxStrLen) { - size_t newSize = (maxStrLen + 16) & (~0xf); - char *newbuffer = (char *) realloc(buffer, newSize); - if(newbuffer) { - size_t oldSize = capacity + 1; // include NULL. - if (newSize > oldSize) - { - memset(newbuffer + oldSize, 0, newSize - oldSize); - } - capacity = newSize - 1; - buffer = newbuffer; - return 1; - } - return 0; + size_t newSize = (maxStrLen + 16) & (~0xf); + char *newbuffer = (char *) realloc(buffer, newSize); + if(newbuffer) { + capacity = newSize - 1; + buffer = newbuffer; + return 1; + } + return 0; } // /*********************************************/ @@ -164,359 +145,413 @@ unsigned char String::changeBuffer(unsigned int maxStrLen) { // /*********************************************/ String & String::copy(const char *cstr, unsigned int length) { - if(!reserve(length)) { - invalidate(); - return *this; - } - len = length; - strcpy(buffer, cstr); - return *this; + if(!reserve(length)) { + invalidate(); + return *this; + } + len = length; + memcpy(buffer, cstr, length); + buffer[len] = '\0'; + return *this; } String & String::copy(const __FlashStringHelper *pstr, unsigned int length) { - if (!reserve(length)) { - invalidate(); - return *this; - } - len = length; - strcpy_P(buffer, (PGM_P)pstr); - return *this; + if (!reserve(length)) { + invalidate(); + return *this; + } + len = length; + memcpy_P(buffer, (PGM_P)pstr, length); + buffer[len] = '\0'; + return *this; } #ifdef __GXX_EXPERIMENTAL_CXX0X__ void String::move(String &rhs) { - if(buffer) { - if(capacity >= rhs.len) { - strcpy(buffer, rhs.buffer); - len = rhs.len; - rhs.len = 0; - return; - } else { - free(buffer); - } - } - buffer = rhs.buffer; - capacity = rhs.capacity; - len = rhs.len; - rhs.buffer = NULL; - rhs.capacity = 0; - rhs.len = 0; + free(buffer); + buffer = rhs.buffer; + capacity = rhs.capacity; + len = rhs.len; + rhs.init(); } #endif -String & String::operator =(const String &rhs) { - if(this == &rhs) - return *this; +String & String::operator =(String const &rhs) { + if(this == &rhs) + return *this; - if(rhs.buffer) - copy(rhs.buffer, rhs.len); - else - invalidate(); + if(rhs.buffer) + copy(rhs.buffer, rhs.len); + else + invalidate(); - return *this; + return *this; } #ifdef __GXX_EXPERIMENTAL_CXX0X__ String & String::operator =(String &&rval) { - if(this != &rval) - move(rval); - return *this; + if(this != &rval) + move(rval); + return *this; } String & String::operator =(StringSumHelper &&rval) { - if(this != &rval) - move(rval); - return *this; + if(this != &rval) + move(rval); + return *this; } #endif String & String::operator =(const char *cstr) { - if(cstr) - copy(cstr, strlen(cstr)); - else - invalidate(); + if(cstr) + copy(cstr, strlen(cstr)); + else + invalidate(); - return *this; + return *this; } String & String::operator = (const __FlashStringHelper *pstr) { - if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); - else invalidate(); + if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); + else invalidate(); - return *this; + return *this; } // /*********************************************/ // /* concat */ // /*********************************************/ -unsigned char String::concat(const String &s) { - return concat(s.buffer, s.len); -} - -unsigned char String::concat(const char *cstr, unsigned int length) { - unsigned int newlen = len + length; - if(!cstr) - return 0; - if(length == 0) - return 1; - if(!reserve(newlen)) - return 0; - strcpy(buffer + len, cstr); - len = newlen; - return 1; +unsigned char String::concat(String const &s) { + return concat(s.buffer, s.len); } unsigned char String::concat(const char *cstr) { - if(!cstr) - return 0; - return concat(cstr, strlen(cstr)); + if(!cstr) + return 0; + return concat(cstr, strlen(cstr)); } -unsigned char String::concat(char c) { - char buf[2]; - buf[0] = c; - buf[1] = 0; - return concat(buf, 1); +unsigned char String::concat(char c, size_t count) { + if (count == 0) + return 1; + unsigned int newlen = len + count; + if(!reserve(newlen)) + return 0; + if (count == 1) buffer[len] = c; + else memset(buffer + len, c, count); + buffer[newlen] = '\0'; + len = newlen; + return 1; } -unsigned char String::concat(unsigned char num) { - char buf[1 + 3 * sizeof(unsigned char)]; - itoa(num, buf, 10); - return concat(buf, strlen(buf)); +unsigned char String::concat(unsigned char num, unsigned char base) { + char buf[1 + 8 * sizeof(unsigned char)]; + utoa(num, buf, base); + return concat(buf, strlen(buf)); } -unsigned char String::concat(int num) { - char buf[2 + 3 * sizeof(int)]; - itoa(num, buf, 10); - return concat(buf, strlen(buf)); +unsigned char String::concat(int num, unsigned char base) { + char buf[2 + 8 * sizeof(int)]; + itoa(num, buf, base); + return concat(buf, strlen(buf)); } -unsigned char String::concat(unsigned int num) { - char buf[1 + 3 * sizeof(unsigned int)]; - utoa(num, buf, 10); - return concat(buf, strlen(buf)); +unsigned char String::concat(unsigned int num, unsigned char base) { + char buf[1 + 8 * sizeof(unsigned int)]; + utoa(num, buf, base); + return concat(buf, strlen(buf)); } -unsigned char String::concat(long num) { - char buf[2 + 3 * sizeof(long)]; - ltoa(num, buf, 10); - return concat(buf, strlen(buf)); +unsigned char String::concat(long num, unsigned char base) { + char buf[2 + 8 * sizeof(long)]; + ltoa(num, buf, base); + return concat(buf, strlen(buf)); } -unsigned char String::concat(unsigned long num) { - char buf[1 + 3 * sizeof(unsigned long)]; - ultoa(num, buf, 10); - return concat(buf, strlen(buf)); +unsigned char String::concat(unsigned long num, unsigned char base) { + char buf[1 + 8 * sizeof(unsigned long)]; + ultoa(num, buf, base); + return concat(buf, strlen(buf)); } -unsigned char String::concat(float num) { - char buf[20]; - char* string = dtostrf(num, 4, 2, buf); - return concat(string, strlen(string)); +unsigned char String::concat(float num, unsigned char decimalPlaces) { + char buf[33]; + dtostrf(num, (decimalPlaces + 2), decimalPlaces, buf); + return concat(buf, strlen(buf)); } -unsigned char String::concat(double num) { - char buf[20]; - char* string = dtostrf(num, 4, 2, buf); - return concat(string, strlen(string)); +unsigned char String::concat(double num, unsigned char decimalPlaces) { + char buf[33]; + dtostrf(num, (decimalPlaces + 2), decimalPlaces, buf); + return concat(buf, strlen(buf)); } unsigned char String::concat(const __FlashStringHelper * str) { - if (!str) return 0; - int length = strlen_P((PGM_P)str); - if (length == 0) return 1; - unsigned int newlen = len + length; - if (!reserve(newlen)) return 0; - strcpy_P(buffer + len, (PGM_P)str); - len = newlen; - return 1; + if (!str) return 0; + int length = strlen_P((PGM_P)str); + if (length == 0) return 1; + unsigned int newlen = len + length; + if (!reserve(newlen)) return 0; + strcpy_P(buffer + len, (PGM_P)str); + len = newlen; + return 1; +} + +unsigned char String::concat(const char *cstr, unsigned int length) { + if(length == 0) + return 1; + if(!cstr) + return 0; + unsigned int newlen = len + length; + if(!reserve(newlen)) + return 0; + memcpy(buffer + len, cstr, length); + buffer[newlen] = '\0'; + len = newlen; + return 1; } /*********************************************/ /* Concatenate */ /*********************************************/ -StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs) { - StringSumHelper &a = const_cast(lhs); - if(!a.concat(rhs.buffer, rhs.len)) - a.invalidate(); - return a; +StringSumHelper & operator +(const StringSumHelper &lhs, String const &rhs) { + StringSumHelper &a = const_cast(lhs); + if(!a.concat(rhs.buffer, rhs.len) && rhs.begin()) + a.invalidate(); + return a; } StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr) { - StringSumHelper &a = const_cast(lhs); - if(!cstr || !a.concat(cstr, strlen(cstr))) - a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if(!a.concat(cstr, strlen(cstr)) && cstr) + a.invalidate(); + return a; } StringSumHelper & operator +(const StringSumHelper &lhs, char c) { - StringSumHelper &a = const_cast(lhs); - if(!a.concat(c)) - a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if(!a.concat(c)) + a.invalidate(); + return a; } StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num) { - StringSumHelper &a = const_cast(lhs); - if(!a.concat(num)) - a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if(!a.concat(num)) + a.invalidate(); + return a; } StringSumHelper & operator +(const StringSumHelper &lhs, int num) { - StringSumHelper &a = const_cast(lhs); - if(!a.concat(num)) - a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if(!a.concat(num)) + a.invalidate(); + return a; } StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num) { - StringSumHelper &a = const_cast(lhs); - if(!a.concat(num)) - a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if(!a.concat(num)) + a.invalidate(); + return a; } StringSumHelper & operator +(const StringSumHelper &lhs, long num) { - StringSumHelper &a = const_cast(lhs); - if(!a.concat(num)) - a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if(!a.concat(num)) + a.invalidate(); + return a; } StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num) { - StringSumHelper &a = const_cast(lhs); - if(!a.concat(num)) - a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if(!a.concat(num)) + a.invalidate(); + return a; } StringSumHelper & operator +(const StringSumHelper &lhs, float num) { - StringSumHelper &a = const_cast(lhs); - if(!a.concat(num)) - a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if(!a.concat(num)) + a.invalidate(); + return a; } StringSumHelper & operator +(const StringSumHelper &lhs, double num) { - StringSumHelper &a = const_cast(lhs); - if(!a.concat(num)) - a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if(!a.concat(num)) + a.invalidate(); + return a; } -StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(rhs)) a.invalidate(); - return a; +StringSumHelper & operator + (const StringSumHelper &lhs, + const __FlashStringHelper *rhs) { + StringSumHelper &a = const_cast(lhs); + if (!a.concat(rhs)) a.invalidate(); + return a; } // /*********************************************/ // /* Comparison */ // /*********************************************/ -int String::compareTo(const String &s) const { - if(!buffer || !s.buffer) { - if(s.buffer && s.len > 0) - return 0 - *(unsigned char *) s.buffer; - if(buffer && len > 0) - return *(unsigned char *) buffer; - return 0; - } - return strcmp(buffer, s.buffer); +int String::compareTo(String const &s, bool ignoreCase) const { + return compareTo(s.buffer, ignoreCase); +} + +int String::compareTo(const char *cstr, bool ignoreCase) const { + const char* aBuf = buffer? buffer : EMPTY.buffer; + const char* bBuf = cstr? cstr : EMPTY.buffer; + return ignoreCase? strcasecmp(aBuf, bBuf): strcmp(aBuf, bBuf); +} + +int String::compareTo(const __FlashStringHelper *str, bool ignoreCase) const { + const char* aBuf = buffer? buffer : EMPTY.buffer; + PGM_P bBuf = str? (PGM_P)str : EMPTY.buffer; + return ignoreCase? strcasecmp_P(aBuf, bBuf): strcmp_P(aBuf, bBuf); + +} + +bool String::equals(String const &s2, bool ignoreCase) const { + return (len == s2.len && compareTo(s2, ignoreCase) == 0); +} + +bool String::equals(const char *cstr, bool ignoreCase) const { + return compareTo(cstr, ignoreCase) == 0; +} + +bool String::equals(const __FlashStringHelper *str, bool ignoreCase) const { + return compareTo(str, ignoreCase) == 0; +} + +bool String::equalsIgnoreCase(String const &s2) const { + return equals(s2, true); +} + +bool String::equalsIgnoreCase(const char *cstr) const { + return equals(cstr, true); +} + +bool String::equalsIgnoreCase(const __FlashStringHelper *str) const { + return equals(str, true); +} + +bool String::equalsConstantTime(String const &s2) const { + // To avoid possible time-based attacks present function + // compares given strings in a constant time. + if(len != s2.len) + return false; + //at this point lengths are the same + if(len == 0) + return true; + //at this point lenghts are the same and non-zero + const char *p1 = buffer; + const char *p2 = s2.buffer; + unsigned int equalchars = 0; + unsigned int diffchars = 0; + while(*p1) { + if(*p1 == *p2) + ++equalchars; + else + ++diffchars; + ++p1; + ++p2; + } + // The following should force a constant time eval of the condition + // without a compiler "logical shortcut" + unsigned char equalcond = (equalchars == len); + unsigned char diffcond = (diffchars == 0); + return (equalcond & diffcond); //bitwise AND +} + +bool String::operator<(String const &rhs) const { + return compareTo(rhs) < 0; } -unsigned char String::equals(const String &s2) const { - return (len == s2.len && compareTo(s2) == 0); +bool String::operator>(String const &rhs) const { + return compareTo(rhs) > 0; } -unsigned char String::equals(const char *cstr) const { - if(len == 0) - return (cstr == NULL || *cstr == 0); - if(cstr == NULL) - return buffer[0] == 0; - return strcmp(buffer, cstr) == 0; +bool String::operator<=(String const &rhs) const { + return compareTo(rhs) <= 0; } -unsigned char String::operator<(const String &rhs) const { - return compareTo(rhs) < 0; +bool String::operator>=(String const &rhs) const { + return compareTo(rhs) >= 0; } -unsigned char String::operator>(const String &rhs) const { - return compareTo(rhs) > 0; +bool String::startsWith(String const &s2, bool ignoreCase) const { + return startsWith(s2, 0, ignoreCase); } -unsigned char String::operator<=(const String &rhs) const { - return compareTo(rhs) <= 0; +bool String::startsWith(String const &s2, unsigned int offset, bool ignoreCase) const { + return startsWith(s2.buffer, s2.len, offset, ignoreCase); } -unsigned char String::operator>=(const String &rhs) const { - return compareTo(rhs) >= 0; +bool String::startsWith(const char *cstr, unsigned int offset, bool ignoreCase) const { + return startsWith(cstr, strlen(cstr), offset, ignoreCase); } -unsigned char String::equalsIgnoreCase(const String &s2) const { - if(this == &s2) - return 1; - if(len != s2.len) - return 0; - if(len == 0) - return 1; - const char *p1 = buffer; - const char *p2 = s2.buffer; - while(*p1) { - if(tolower(*p1++) != tolower(*p2++)) - return 0; - } - return 1; +bool String::startsWith(const char *cstr, unsigned int bLen, + unsigned int offset, bool ignoreCase) const { + if (!bLen) return 1; + if (offset + bLen > len) return 0; + const char* cBuf = buffer+offset; + return (ignoreCase? strncasecmp(cBuf, cstr, bLen) + : strncmp(cBuf, cstr, bLen)) == 0; } -unsigned char String::equalsConstantTime(const String &s2) const { - // To avoid possible time-based attacks present function - // compares given strings in a constant time. - if(len != s2.len) - return 0; - //at this point lengths are the same - if(len == 0) - return 1; - //at this point lenghts are the same and non-zero - const char *p1 = buffer; - const char *p2 = s2.buffer; - unsigned int equalchars = 0; - unsigned int diffchars = 0; - while(*p1) { - if(*p1 == *p2) - ++equalchars; - else - ++diffchars; - ++p1; - ++p2; - } - //the following should force a constant time eval of the condition without a compiler "logical shortcut" - unsigned char equalcond = (equalchars == len); - unsigned char diffcond = (diffchars == 0); - return (equalcond & diffcond); //bitwise AND +bool String::startsWith(const __FlashStringHelper *str, unsigned int offset, + bool ignoreCase) const { + return startsWith(str, strlen_P((PGM_P)str), offset, ignoreCase); } -unsigned char String::startsWith(const String &s2) const { - if(len < s2.len) - return 0; - return startsWith(s2, 0); +bool String::startsWith(const __FlashStringHelper *str, unsigned int bLen, + unsigned int offset, bool ignoreCase) const { + if (!bLen) return 1; + if (offset + bLen > len) return 0; + const char* cBuf = buffer+offset; + return (ignoreCase? strncasecmp_P(cBuf, (PGM_P)str, bLen) + : strncmp_P(cBuf, (PGM_P)str, bLen)) == 0; } -unsigned char String::startsWith(const String &s2, unsigned int offset) const { - if(offset > len - s2.len || !buffer || !s2.buffer) - return 0; - return strncmp(&buffer[offset], s2.buffer, s2.len) == 0; +bool String::endsWith(String const &s2, bool ignoreCase) const { + return endsWith(s2, 0, ignoreCase); } -unsigned char String::endsWith(const String &s2) const { - if(len < s2.len || !buffer || !s2.buffer) - return 0; - return strcmp(&buffer[len - s2.len], s2.buffer) == 0; +bool String::endsWith(String const &s2, unsigned int offset, + bool ignoreCase) const { + return endsWith(s2.buffer, s2.len, offset, ignoreCase); +} + +bool String::endsWith(const char *cstr, unsigned int offset, + bool ignoreCase) const { + return endsWith(cstr, strlen(cstr), offset, ignoreCase); +} + +bool String::endsWith(const char *cstr, unsigned int bLen, + unsigned int offset, bool ignoreCase) const { + if (!bLen) return 1; + if (offset + bLen > len) return 0; + const char* cBuf = buffer+len-offset-bLen; + return (ignoreCase? strncasecmp(cBuf, cstr, bLen) : strncmp(cBuf, cstr, bLen)) == 0; +} + +bool String::endsWith(const __FlashStringHelper *str, unsigned int offset, + bool ignoreCase) const { + return endsWith(str, strlen_P((PGM_P)str), offset, ignoreCase); +} + +bool String::endsWith(const __FlashStringHelper *str, unsigned int bLen, + unsigned int offset, bool ignoreCase) const { + if (!bLen) return 1; + if (offset + bLen > len) return 0; + const char* cBuf = buffer+len-offset-bLen; + return (ignoreCase? strncasecmp_P(cBuf, (PGM_P)str, bLen) + : strncmp_P(cBuf, (PGM_P)str, bLen)) == 0; } // /*********************************************/ @@ -524,41 +559,41 @@ unsigned char String::endsWith(const String &s2) const { // /*********************************************/ char String::charAt(unsigned int loc) const { - return operator[](loc); + return operator[](loc); } void String::setCharAt(unsigned int loc, char c) { - if(loc < len) - buffer[loc] = c; + if(loc < len) + buffer[loc] = c; } char & String::operator[](unsigned int index) { - static char dummy_writable_char; - if(index >= len || !buffer) { - dummy_writable_char = 0; - return dummy_writable_char; - } - return buffer[index]; + static char dummy_writable_char; + if(index >= len || !buffer) { + dummy_writable_char = 0; + return dummy_writable_char; + } + return buffer[index]; } char String::operator[](unsigned int index) const { - if(index >= len || !buffer) - return 0; - return buffer[index]; + if(index >= len || !buffer) + return 0; + return buffer[index]; } void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const { - if(!bufsize || !buf) - return; - if(index >= len) { - buf[0] = 0; - return; - } - unsigned int n = bufsize - 1; - if(n > len - index) - n = len - index; - strncpy((char *) buf, buffer + index, n); - buf[n] = 0; + if(!bufsize || !buf) + return; + if(index >= len) { + buf[0] = 0; + return; + } + unsigned int n = bufsize - 1; + if(n > len - index) + n = len - index; + memcpy((char *) buf, buffer + index, n); + buf[n] = 0; } // /*********************************************/ @@ -566,83 +601,76 @@ void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int ind // /*********************************************/ int String::indexOf(char c) const { - return indexOf(c, 0); + return indexOf(c, 0); } int String::indexOf(char ch, unsigned int fromIndex) const { - if(fromIndex >= len) - return -1; - const char* temp = strchr(buffer + fromIndex, ch); - if(temp == NULL) - return -1; - return temp - buffer; + if(fromIndex >= len) + return -1; + const char* temp = strchr(buffer + fromIndex, ch); + if(temp == NULL) + return -1; + return temp - buffer; } -int String::indexOf(const String &s2) const { - return indexOf(s2, 0); +int String::indexOf(String const &s2) const { + return indexOf(s2, 0); } -int String::indexOf(const String &s2, unsigned int fromIndex) const { - if(fromIndex >= len) - return -1; - const char *found = strstr(buffer + fromIndex, s2.buffer); - if(found == NULL) - return -1; - return found - buffer; +int String::indexOf(String const &s2, unsigned int fromIndex) const { + if(fromIndex >= len) + return -1; + if(!s2) + return fromIndex; + const char *found = strstr(buffer + fromIndex, s2.buffer); + if(found == NULL) + return -1; + return found - buffer; } int String::lastIndexOf(char theChar) const { - return lastIndexOf(theChar, len - 1); + return lastIndexOf(theChar, len - 1); } int String::lastIndexOf(char ch, unsigned int fromIndex) const { - if(fromIndex >= len) - return -1; - char tempchar = buffer[fromIndex + 1]; - buffer[fromIndex + 1] = '\0'; - char* temp = strrchr(buffer, ch); - buffer[fromIndex + 1] = tempchar; - if(temp == NULL) - return -1; - return temp - buffer; -} - -int String::lastIndexOf(const String &s2) const { - return lastIndexOf(s2, len - s2.len); -} - -int String::lastIndexOf(const String &s2, unsigned int fromIndex) const { - if(s2.len == 0 || len == 0 || s2.len > len) - return -1; - if(fromIndex >= len) - fromIndex = len - 1; - int found = -1; - for(char *p = buffer; p <= buffer + fromIndex; p++) { - p = strstr(p, s2.buffer); - if(!p) - break; - if((unsigned int) (p - buffer) <= fromIndex) - found = p - buffer; - } - return found; + if(fromIndex >= len) + return -1; + char tempchar = buffer[fromIndex + 1]; + buffer[fromIndex + 1] = '\0'; + char* temp = strrchr(buffer, ch); + buffer[fromIndex + 1] = tempchar; + if(temp == NULL) + return -1; + return temp - buffer; +} + +int String::lastIndexOf(String const &s2) const { + return lastIndexOf(s2, len - s2.len); +} + +int String::lastIndexOf(String const &s2, unsigned int fromIndex) const { + if(s2.len == 0 || len == 0 || s2.len > len) + return -1; + if(fromIndex >= len) + fromIndex = len - 1; + int found = -1; + for(char *p = buffer; p <= buffer + fromIndex; p++) { + p = strstr(p, s2.buffer); + if(!p) + break; + if((unsigned int) (p - buffer) <= fromIndex) + found = p - buffer; + } + return found; } String String::substring(unsigned int left, unsigned int right) const { - if(left > right) { - unsigned int temp = right; - right = left; - left = temp; - } - String out; - if(left >= len) - return out; - if(right > len) - right = len; - char temp = buffer[right]; // save the replaced character - buffer[right] = '\0'; - out = buffer + left; // pointer arithmetic - buffer[right] = temp; //restore character - return out; + String out; + if(left < right && left < len) { + if(right > len) right = len; + out.concat(buffer+left, right-left); + } + return std::move(out); } // /*********************************************/ @@ -650,125 +678,188 @@ String String::substring(unsigned int left, unsigned int right) const { // /*********************************************/ void String::replace(char find, char replace) { - if(!buffer) - return; - for(char *p = buffer; *p; p++) { - if(*p == find) - *p = replace; - } + if(!buffer) + return; + for(char *p = buffer; (unsigned int)(p-buffer) < len; p++) { + if(*p == find) *p = replace; + } } void String::replace(const String& find, const String& replace) { - if(len == 0 || find.len == 0) - return; - int diff = replace.len - find.len; - char *readFrom = buffer; - char *foundAt; - if(diff == 0) { - while((foundAt = strstr(readFrom, find.buffer)) != NULL) { - memcpy(foundAt, replace.buffer, replace.len); - readFrom = foundAt + replace.len; - } - } else if(diff < 0) { - char *writeTo = buffer; - while((foundAt = strstr(readFrom, find.buffer)) != NULL) { - unsigned int n = foundAt - readFrom; - memcpy(writeTo, readFrom, n); - writeTo += n; - memcpy(writeTo, replace.buffer, replace.len); - writeTo += replace.len; - readFrom = foundAt + find.len; - len += diff; - } - strcpy(writeTo, readFrom); - } else { - unsigned int size = len; // compute size needed for result - while((foundAt = strstr(readFrom, find.buffer)) != NULL) { - readFrom = foundAt + find.len; - size += diff; - } - if(size == len) - return; - if(size > capacity && !changeBuffer(size)) - return; // XXX: tell user! - int index = len - 1; - while(index >= 0 && (index = lastIndexOf(find, index)) >= 0) { - readFrom = buffer + index + find.len; - memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); - len += diff; - buffer[len] = 0; - memcpy(buffer + index, replace.buffer, replace.len); - index--; - } - } + if(len == 0 || find.len == 0) + return; + int diff = replace.len - find.len; + char *readFrom = buffer; + char *foundAt; + if(diff == 0) { + while((foundAt = strstr(readFrom, find.buffer)) != NULL) { + memcpy(foundAt, replace.buffer, replace.len); + readFrom = foundAt + replace.len; + } + } else if(diff < 0) { + char *writeTo = buffer; + while((foundAt = strstr(readFrom, find.buffer)) != NULL) { + unsigned int n = foundAt - readFrom; + memcpy(writeTo, readFrom, n); + writeTo += n; + memcpy(writeTo, replace.buffer, replace.len); + writeTo += replace.len; + readFrom = foundAt + find.len; + len += diff; + } + strcpy(writeTo, readFrom); + } else { + unsigned int size = len; // compute size needed for result + while((foundAt = strstr(readFrom, find.buffer)) != NULL) { + readFrom = foundAt + find.len; + size += diff; + } + if(size == len) + return; + if(size > capacity && !changeBuffer(size)) + return; // XXX: tell user! + int index = len - 1; + while(index >= 0 && (index = lastIndexOf(find, index)) >= 0) { + readFrom = buffer + index + find.len; + memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); + len += diff; + buffer[len] = 0; + memcpy(buffer + index, replace.buffer, replace.len); + index--; + } + } } void String::remove(unsigned int index) { - // Pass the biggest integer as the count. The remove method - // below will take care of truncating it at the end of the - // string. - remove(index, (unsigned int) -1); + // Pass the biggest integer as the count. The remove method + // below will take care of truncating it at the end of the + // string. + remove(index, (unsigned int) -1); } void String::remove(unsigned int index, unsigned int count) { - if(index >= len) { - return; - } - if(count <= 0) { - return; - } - if(count > len - index) { - count = len - index; - } - char *writeTo = buffer + index; - len = len - count; - strncpy(writeTo, buffer + index + count, len - index); - buffer[len] = 0; + if(index >= len || count <= 0) { + return; + } + if(count < len - index) { + char *writeTo = buffer + index; + memmove(writeTo, writeTo + count, len - count - index); + } else { + count = len - index; + } + len = len - count; + buffer[len] = 0; } void String::toLowerCase(void) { - if(!buffer) - return; - for(char *p = buffer; *p; p++) { - *p = tolower(*p); - } + if(!buffer) + return; + for(char *p = buffer; *p; p++) { + *p = tolower(*p); + } } void String::toUpperCase(void) { - if(!buffer) - return; - for(char *p = buffer; *p; p++) { - *p = toupper(*p); - } + if(!buffer) + return; + for(char *p = buffer; *p; p++) { + *p = toupper(*p); + } } void String::trim(void) { - if(!buffer || len == 0) - return; - char *begin = buffer; - while(isspace(*begin)) - begin++; - char *end = buffer + len - 1; - while(isspace(*end) && end >= begin) - end--; - len = end + 1 - begin; - if(begin > buffer) - memcpy(buffer, begin, len); - buffer[len] = 0; + if(!buffer || len == 0) + return; + char *begin = buffer; + while(isspace(*begin)) + begin++; + char *end = buffer + len - 1; + while(isspace(*end) && end >= begin) + end--; + len = end + 1 - begin; + if(begin > buffer) + memcpy(buffer, begin, len); + buffer[len] = 0; +} + +bool String::empty(void) const { + return len == 0; +} + +void String::clear(bool free) { + if (free) invalidate(); + else if (len) { + len = 0; + buffer[len] = 0; + } } // /*********************************************/ // /* Parsing / Conversion */ // /*********************************************/ -long String::toInt(void) const { - if(buffer) - return atol(buffer); - return 0; +int String::toInt(void) const { + int Ret; + if (toInt(Ret)) return Ret; + return 0; } float String::toFloat(void) const { - if(buffer) - return atof(buffer); - return 0; + float Ret; + if (toFloat(Ret)) return Ret; + return 0; +} + +bool String::toInt(int &val, unsigned char base) const { + long ParseVal; + bool Ret = toLong(ParseVal, base); + return val = ParseVal, Ret; +} + +bool String::toUInt(unsigned int &val, unsigned char base) const { + unsigned long ParseVal; + bool Ret = toULong(ParseVal, base); + return val = ParseVal, Ret; +} + +bool String::toLong(long &val, unsigned char base) const { + if (empty()) return false; + char *endptr; + val = strtol(buffer, &endptr, base); + return endptr == end(); +} + +bool String::toULong(unsigned long &val, unsigned char base) const { + if (empty()) return false; + char *endptr; + val = strtoul(buffer, &endptr, base); + return endptr == end(); +} + +bool String::toLLong(long long &val, unsigned char base) const { + if (empty()) return false; + char *endptr; + val = strtoll(buffer, &endptr, base); + return endptr == end(); +} + +bool String::toULLong(unsigned long long &val, unsigned char base) const { + if (empty()) return false; + char *endptr; + val = strtoull(buffer, &endptr, base); + return endptr == end(); +} + +bool String::toFloat(float &val) const { + if (empty()) return false; + char *endptr; + val = strtof(buffer, &endptr); + return endptr == end(); +} + +bool String::toDouble(double &val) const { + if (empty()) return false; + char *endptr; + val = strtod(buffer, &endptr); + return endptr == end(); } diff --git a/cores/esp8266/WString.h b/cores/esp8266/WString.h index fbf3c59b2f..8c82d66851 100644 --- a/cores/esp8266/WString.h +++ b/cores/esp8266/WString.h @@ -3,6 +3,7 @@ ...mostly rewritten by Paul Stoffregen... Copyright (c) 2009-10 Hernando Barragan. All right reserved. Copyright 2011, Paul Stoffregen, paul@pjrc.com + Modified by Zhenyu Wu for VFATFS, 2017.01 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -35,263 +36,262 @@ class StringSumHelper; // an abstract class used as a means to proide a unique pointer type // but really has no body class __FlashStringHelper; -#define FPSTR(pstr_pointer) (reinterpret_cast(pstr_pointer)) +#define FPSTR(pstr_pointer) \ + (reinterpret_cast(pstr_pointer)) #define F(string_literal) (FPSTR(PSTR(string_literal))) // The string class class String { - // use a function pointer to allow for "if (s)" without the - // complications of an operator bool(). for more information, see: - // http://www.artima.com/cppsource/safebool.html - typedef void (String::*StringIfHelperType)() const; - void StringIfHelper() const { - } - - public: - // constructors - // creates a copy of the initial value. - // if the initial value is null or invalid, or if memory allocation - // fails, the string will be marked as invalid (i.e. "if (s)" will - // be false). - String(const char *cstr = ""); - String(const String &str); - String(const __FlashStringHelper *str); + // use a function pointer to allow for "if (s)" without the + // complications of an operator bool(). for more information, see: + // http://www.artima.com/cppsource/safebool.html + typedef void (String::*StringIfHelperType)() const; + void StringIfHelper() const {} + + public: + // constructors + // creates a copy of the initial value. + // if the initial value is null or invalid, or if memory allocation + // fails, the string will be marked as invalid (i.e. "if (s)" will + // be false). + String(const char *cstr = "", size_t len = 0); + String(String const &str); + String(const __FlashStringHelper *str, size_t len = 0); #ifdef __GXX_EXPERIMENTAL_CXX0X__ - String(String &&rval); - String(StringSumHelper &&rval); + String(String &&rval); + String(StringSumHelper &&rval); #endif - explicit String(char c); - explicit String(unsigned char, unsigned char base = 10); - explicit String(int, unsigned char base = 10); - explicit String(unsigned int, unsigned char base = 10); - explicit String(long, unsigned char base = 10); - explicit String(unsigned long, unsigned char base = 10); - explicit String(float, unsigned char decimalPlaces = 2); - explicit String(double, unsigned char decimalPlaces = 2); - ~String(void); - - // memory management - // return true on success, false on failure (in which case, the string - // is left unchanged). reserve(0), if successful, will validate an - // invalid string (i.e., "if (s)" will be true afterwards) - unsigned char reserve(unsigned int size); - inline unsigned int length(void) const { - if(buffer) { - return len; - } else { - return 0; - } - } - - // creates a copy of the assigned value. if the value is null or - // invalid, or if the memory allocation fails, the string will be - // marked as invalid ("if (s)" will be false). - String & operator =(const String &rhs); - String & operator =(const char *cstr); - String & operator = (const __FlashStringHelper *str); + explicit String(char c, size_t count = 1); + explicit String(unsigned char, unsigned char base = 10); + explicit String(int, unsigned char base = 10); + explicit String(unsigned int, unsigned char base = 10); + explicit String(long, unsigned char base = 10); + explicit String(unsigned long, unsigned char base = 10); + explicit String(float, unsigned char decimalPlaces = 2); + explicit String(double, unsigned char decimalPlaces = 2); + ~String(void); + + static String const EMPTY; + + // memory management + // return true on success, false on failure (in which case, the string + // is left unchanged). + unsigned char reserve(unsigned int size); + inline unsigned int length(void) const { return buffer? len: 0; } + + // creates a copy of the assigned value. if the value is null or + // invalid, or if the memory allocation fails, the string will be + // marked as invalid ("if (s)" will be false). + String & operator = (String const &rhs); + String & operator = (const char *cstr); + String & operator = (const __FlashStringHelper *str); #ifdef __GXX_EXPERIMENTAL_CXX0X__ - String & operator =(String &&rval); - String & operator =(StringSumHelper &&rval); + String & operator = (String &&rval); + String & operator = (StringSumHelper &&rval); #endif - // concatenate (works w/ built-in types) - - // returns true on success, false on failure (in which case, the string - // is left unchanged). if the argument is null or invalid, the - // concatenation is considered unsucessful. - unsigned char concat(const String &str); - unsigned char concat(const char *cstr); - unsigned char concat(char c); - unsigned char concat(unsigned char c); - unsigned char concat(int num); - unsigned char concat(unsigned int num); - unsigned char concat(long num); - unsigned char concat(unsigned long num); - unsigned char concat(float num); - unsigned char concat(double num); - unsigned char concat(const __FlashStringHelper * str); - - // if there's not enough memory for the concatenated value, the string - // will be left unchanged (but this isn't signalled in any way) - String & operator +=(const String &rhs) { - concat(rhs); - return (*this); - } - String & operator +=(const char *cstr) { - concat(cstr); - return (*this); - } - String & operator +=(char c) { - concat(c); - return (*this); - } - String & operator +=(unsigned char num) { - concat(num); - return (*this); - } - String & operator +=(int num) { - concat(num); - return (*this); - } - String & operator +=(unsigned int num) { - concat(num); - return (*this); - } - String & operator +=(long num) { - concat(num); - return (*this); - } - String & operator +=(unsigned long num) { - concat(num); - return (*this); - } - String & operator +=(float num) { - concat(num); - return (*this); - } - String & operator +=(double num) { - concat(num); - return (*this); - } - String & operator += (const __FlashStringHelper *str){ - concat(str); - return (*this); - } - - friend StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs); - friend StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr); - friend StringSumHelper & operator +(const StringSumHelper &lhs, char c); - friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num); - friend StringSumHelper & operator +(const StringSumHelper &lhs, int num); - friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num); - friend StringSumHelper & operator +(const StringSumHelper &lhs, long num); - friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num); - friend StringSumHelper & operator +(const StringSumHelper &lhs, float num); - friend StringSumHelper & operator +(const StringSumHelper &lhs, double num); - friend StringSumHelper & operator +(const StringSumHelper &lhs, const __FlashStringHelper *rhs); - - // comparison (only works w/ Strings and "strings") - operator StringIfHelperType() const { - return buffer ? &String::StringIfHelper : 0; - } - int compareTo(const String &s) const; - unsigned char equals(const String &s) const; - unsigned char equals(const char *cstr) const; - unsigned char operator ==(const String &rhs) const { - return equals(rhs); - } - unsigned char operator ==(const char *cstr) const { - return equals(cstr); - } - unsigned char operator !=(const String &rhs) const { - return !equals(rhs); - } - unsigned char operator !=(const char *cstr) const { - return !equals(cstr); - } - unsigned char operator <(const String &rhs) const; - unsigned char operator >(const String &rhs) const; - unsigned char operator <=(const String &rhs) const; - unsigned char operator >=(const String &rhs) const; - unsigned char equalsIgnoreCase(const String &s) const; - unsigned char equalsConstantTime(const String &s) const; - unsigned char startsWith(const String &prefix) const; - unsigned char startsWith(const String &prefix, unsigned int offset) const; - unsigned char endsWith(const String &suffix) const; - - // character acccess - char charAt(unsigned int index) const; - void setCharAt(unsigned int index, char c); - char operator [](unsigned int index) const; - char& operator [](unsigned int index); - void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index = 0) const; - void toCharArray(char *buf, unsigned int bufsize, unsigned int index = 0) const { - getBytes((unsigned char *) buf, bufsize, index); - } - const char* c_str() const { return buffer; } - char* begin() { return buffer; } - char* end() { return buffer + length(); } - const char* begin() const { return c_str(); } - const char* end() const { return c_str() + length(); } - - // search - int indexOf(char ch) const; - int indexOf(char ch, unsigned int fromIndex) const; - int indexOf(const String &str) const; - int indexOf(const String &str, unsigned int fromIndex) const; - int lastIndexOf(char ch) const; - int lastIndexOf(char ch, unsigned int fromIndex) const; - int lastIndexOf(const String &str) const; - int lastIndexOf(const String &str, unsigned int fromIndex) const; - String substring(unsigned int beginIndex) const { - return substring(beginIndex, len); - } - ; - String substring(unsigned int beginIndex, unsigned int endIndex) const; - - // modification - void replace(char find, char replace); - void replace(const String& find, const String& replace); - void remove(unsigned int index); - void remove(unsigned int index, unsigned int count); - void toLowerCase(void); - void toUpperCase(void); - void trim(void); - - // parsing/conversion - long toInt(void) const; - float toFloat(void) const; - - protected: - char *buffer; // the actual char array - unsigned int capacity; // the array length minus one (for the '\0') - unsigned int len; // the String length (not counting the '\0') - protected: - void init(void); - void invalidate(void); - unsigned char changeBuffer(unsigned int maxStrLen); - unsigned char concat(const char *cstr, unsigned int length); - - // copy and move - String & copy(const char *cstr, unsigned int length); - String & copy(const __FlashStringHelper *pstr, unsigned int length); + // concatenate (works w/ built-in types) + + // returns true on success, false on failure (in which case, the string + // is left unchanged). if the argument is null or invalid, the + // concatenation is considered unsucessful. + unsigned char concat(String const &str); + unsigned char concat(const char *cstr); + unsigned char concat(char c, size_t count = 1); + unsigned char concat(unsigned char num, unsigned char base = 10); + unsigned char concat(int num, unsigned char base = 10); + unsigned char concat(unsigned int num, unsigned char base = 10); + unsigned char concat(long num, unsigned char base = 10); + unsigned char concat(unsigned long num, unsigned char base = 10); + unsigned char concat(float num, unsigned char decimalPlaces = 2); + unsigned char concat(double num, unsigned char decimalPlaces = 2); + + unsigned char concat(const __FlashStringHelper *str); + unsigned char concat(const char *cstr, unsigned int length); + + // if there's not enough memory for the concatenated value, the string + // will be left unchanged (but this isn't signalled in any way) + String & operator +=(String const &rhs) { return concat(rhs), *this; } + String & operator +=(const char *cstr) { return concat(cstr), *this; } + String & operator +=(char c) { return concat(c), *this; } + String & operator +=(unsigned char num){ return concat(num), *this; } + String & operator +=(int num) { return concat(num), *this; } + String & operator +=(unsigned int num) { return concat(num), *this; } + String & operator +=(long num) { return concat(num), *this; } + String & operator +=(unsigned long num) { return concat(num), *this; } + String & operator +=(float num) { return concat(num), *this; } + String & operator +=(double num) { return concat(num), *this; } + String & operator += (const __FlashStringHelper *str) + { return concat(str), *this; } + + friend StringSumHelper & operator +(const StringSumHelper &lhs, + String const &rhs); + friend StringSumHelper & operator +(const StringSumHelper &lhs, + const char *cstr); + friend StringSumHelper & operator +(const StringSumHelper &lhs, + char c); + friend StringSumHelper & operator +(const StringSumHelper &lhs, + unsigned char num); + friend StringSumHelper & operator +(const StringSumHelper &lhs, + int num); + friend StringSumHelper & operator +(const StringSumHelper &lhs, + unsigned int num); + friend StringSumHelper & operator +(const StringSumHelper &lhs, + long num); + friend StringSumHelper & operator +(const StringSumHelper &lhs, + unsigned long num); + friend StringSumHelper & operator +(const StringSumHelper &lhs, + float num); + friend StringSumHelper & operator +(const StringSumHelper &lhs, + double num); + friend StringSumHelper & operator +(const StringSumHelper &lhs, + const __FlashStringHelper *rhs); + + // comparison (only works w/ Strings and "strings") + int compareTo(String const &s, bool ignoreCase = false) const; + int compareTo(const char *cstr, bool ignoreCase = false) const; + int compareTo(const __FlashStringHelper *str, + bool ignoreCase = false) const; + + bool equals(String const &s, bool ignoreCase = false) const; + bool equals(const char *cstr, bool ignoreCase = false) const; + bool equals(const __FlashStringHelper *str, + bool ignoreCase = false) const; + + bool equalsIgnoreCase(String const &s) const; + bool equalsIgnoreCase(const char *cstr) const; + bool equalsIgnoreCase(const __FlashStringHelper *str) const; + + bool equalsConstantTime(String const &s) const; + + bool operator ==(String const &rhs) const { return equals(rhs); } + bool operator ==(const char *cstr) const { return equals(cstr); } + bool operator ==(const __FlashStringHelper *str) const + { return equals(str); } + bool operator !=(String const &rhs) const { return !equals(rhs); } + bool operator !=(const char *cstr) const { return !equals(cstr); } + bool operator !=(const __FlashStringHelper *str) const + { return !equals(str); } + + bool operator <(String const &rhs) const; + bool operator >(String const &rhs) const; + bool operator <=(String const &rhs) const; + bool operator >=(String const &rhs) const; + + bool startsWith(String const &prefix, bool ignoreCase = false) const; + bool startsWith(String const &prefix, unsigned int offset, + bool ignoreCase = false) const; + bool startsWith(const char *cstr, unsigned int offset, + bool ignoreCase = false) const; + bool startsWith(const char *cstr, unsigned int bLen, + unsigned int offset, bool ignoreCase = false) const; + bool startsWith(const __FlashStringHelper *str, unsigned int offset = 0, + bool ignoreCase = false) const; + bool startsWith(const __FlashStringHelper *str, unsigned int bLen, + unsigned int offset, bool ignoreCase = false) const; + + bool endsWith(String const &suffix, bool ignoreCase = false) const; + bool endsWith(String const &prefix, unsigned int offset, + bool ignoreCase = false) const; + bool endsWith(const char *cstr, unsigned int offset, + bool ignoreCase = false) const; + bool endsWith(const char *cstr, unsigned int bLen, + unsigned int offset, bool ignoreCase = false) const; + bool endsWith(const __FlashStringHelper *str, + unsigned int offset = 0, bool ignoreCase = false) const; + bool endsWith(const __FlashStringHelper *str, + unsigned int bLen, unsigned int offset, + bool ignoreCase = false) const; + + // character acccess + char charAt(unsigned int index) const; + void setCharAt(unsigned int index, char c); + char operator [](unsigned int index) const; + char& operator [](unsigned int index); + void getBytes(unsigned char *buf, unsigned int bufsize, + unsigned int index = 0) const; + void toCharArray(char *buf, unsigned int bufsize, + unsigned int index = 0) const + { getBytes((unsigned char *) buf, bufsize, index); } + + const char* c_str() const + { return buffer? buffer : EMPTY.begin(); } + char* begin() { return &(*this)[0]; } + char* end() { return begin() + length(); } + const char* begin() const { return c_str(); } + const char* end() const { return begin() + length(); } + + // search + int indexOf(char ch) const; + int indexOf(char ch, unsigned int fromIndex) const; + int indexOf(String const &str) const; + int indexOf(String const &str, unsigned int fromIndex) const; + int lastIndexOf(char ch) const; + int lastIndexOf(char ch, unsigned int fromIndex) const; + int lastIndexOf(String const &str) const; + int lastIndexOf(String const &str, unsigned int fromIndex) const; + + String substring(unsigned int beginIndex) const + { return substring(beginIndex, len); } + String substring(unsigned int beginIndex, unsigned int endIndex) const; + + // modification + void replace(char find, char replace); + void replace(String const& find, String const& replace); + void remove(unsigned int index); + void remove(unsigned int index, unsigned int count); + void toLowerCase(void); + void toUpperCase(void); + void trim(void); + + // parsing/conversion + int toInt(void) const; + float toFloat(void) const; + + bool toInt(int &val, unsigned char base = 10) const; + bool toUInt(unsigned int &val, unsigned char base = 10) const; + bool toLong(long &val, unsigned char base = 10) const; + bool toULong(unsigned long &val, unsigned char base = 10) const; + bool toLLong(long long &val, unsigned char base = 10) const; + bool toULLong(unsigned long long &val, unsigned char base = 10) const; + bool toFloat(float &val) const; + bool toDouble(double &val) const; + + bool empty(void) const; + void clear(bool free = false); + + operator StringIfHelperType() const + { return empty() ? 0 : &String::StringIfHelper; } + + protected: + char *buffer; // the actual char array + unsigned int capacity; // the array length minus one (for the '\0') + unsigned int len; // the String length (not counting the '\0') + + void init(void); + void invalidate(void); + unsigned char changeBuffer(unsigned int maxStrLen); + + // copy and move + String & copy(const char *cstr, unsigned int length); + String & copy(const __FlashStringHelper *pstr, unsigned int length); #ifdef __GXX_EXPERIMENTAL_CXX0X__ - void move(String &rhs); + void move(String &rhs); #endif }; class StringSumHelper: public String { - public: - StringSumHelper(const String &s) : - String(s) { - } - StringSumHelper(const char *p) : - String(p) { - } - StringSumHelper(char c) : - String(c) { - } - StringSumHelper(unsigned char num) : - String(num) { - } - StringSumHelper(int num) : - String(num) { - } - StringSumHelper(unsigned int num) : - String(num) { - } - StringSumHelper(long num) : - String(num) { - } - StringSumHelper(unsigned long num) : - String(num) { - } - StringSumHelper(float num) : - String(num) { - } - StringSumHelper(double num) : - String(num) { - } + public: + StringSumHelper(String const &s) : String(s) {} + StringSumHelper(const char *p) : String(p) {} + StringSumHelper(char c) : String(c) {} + StringSumHelper(unsigned char num) : String(num) {} + StringSumHelper(int num) : String(num) {} + StringSumHelper(unsigned int num) : String(num) {} + StringSumHelper(long num) : String(num) {} + StringSumHelper(unsigned long num) : String(num) {} + StringSumHelper(float num) : String(num) {} + StringSumHelper(double num) : String(num) {} }; #endif // __cplusplus diff --git a/cores/esp8266/cont_util.c b/cores/esp8266/cont_util.c index 08704702b6..15be292eb7 100644 --- a/cores/esp8266/cont_util.c +++ b/cores/esp8266/cont_util.c @@ -20,15 +20,12 @@ #include "cont.h" #include -#include #include "ets_sys.h" #define CONT_STACKGUARD 0xfeefeffe void cont_init(cont_t* cont) { - memset(cont, 0, sizeof(cont_t)); - cont->stack_guard1 = CONT_STACKGUARD; cont->stack_guard2 = CONT_STACKGUARD; cont->stack_end = cont->stack + (sizeof(cont->stack) / 4); diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 52ba57857b..cb7401366e 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -37,30 +37,11 @@ extern "C" { #define LOOP_TASK_PRIORITY 1 #define LOOP_QUEUE_SIZE 1 -#define OPTIMISTIC_YIELD_TIME_US 16000 -extern "C" void call_user_start(); -extern void loop(); -extern void setup(); -extern void (*__init_array_start)(void); -extern void (*__init_array_end)(void); +#define OPTIMISTIC_YIELD_TIME_US 16000 -/* Not static, used in Esp.cpp */ struct rst_info resetInfo; -/* Not static, used in core_esp8266_postmortem.c. - * Placed into noinit section because we assign value to this variable - * before .bss is zero-filled, and need to preserve the value. - */ -cont_t* g_pcont __attribute__((section(".noinit"))); - -/* Event queue used by the main (arduino) task */ -static os_event_t s_loop_queue[LOOP_QUEUE_SIZE]; - -/* Used to implement optimistic_yield */ -static uint32_t s_micros_at_task_start; - - extern "C" { extern const uint32_t __attribute__((section(".ver_number"))) core_version = ARDUINO_ESP8266_GIT_VER; const char* core_release = @@ -71,10 +52,19 @@ const char* core_release = #endif } // extern "C" +int atexit(void (*func)()) { + (void) func; + return 0; +} + +extern "C" void ets_update_cpu_frequency(int freqmhz); void initVariant() __attribute__((weak)); void initVariant() { } +extern void loop(); +extern void setup(); + void preloop_update_frequency() __attribute__((weak)); void preloop_update_frequency() { #if defined(F_CPU) && (F_CPU == 160000000L) @@ -83,10 +73,17 @@ void preloop_update_frequency() { #endif } +extern void (*__init_array_start)(void); +extern void (*__init_array_end)(void); + +cont_t g_cont __attribute__ ((aligned (16))); +static os_event_t g_loop_queue[LOOP_QUEUE_SIZE]; + +static uint32_t g_micros_at_task_start; extern "C" void esp_yield() { - if (cont_can_yield(g_pcont)) { - cont_yield(g_pcont); + if (cont_can_yield(&g_cont)) { + cont_yield(&g_cont); } } @@ -95,7 +92,7 @@ extern "C" void esp_schedule() { } extern "C" void __yield() { - if (cont_can_yield(g_pcont)) { + if (cont_can_yield(&g_cont)) { esp_schedule(); esp_yield(); } @@ -107,8 +104,8 @@ extern "C" void __yield() { extern "C" void yield(void) __attribute__ ((weak, alias("__yield"))); extern "C" void optimistic_yield(uint32_t interval_us) { - if (cont_can_yield(g_pcont) && - (system_get_time() - s_micros_at_task_start) > interval_us) + if (cont_can_yield(&g_cont) && + (system_get_time() - g_micros_at_task_start) > interval_us) { yield(); } @@ -128,9 +125,9 @@ static void loop_wrapper() { static void loop_task(os_event_t *events) { (void) events; - s_micros_at_task_start = system_get_time(); - cont_run(g_pcont, &loop_wrapper); - if (cont_check(g_pcont) != 0) { + g_micros_at_task_start = system_get_time(); + cont_run(&g_cont, &loop_wrapper); + if (cont_check(&g_cont) != 0) { panic(); } } @@ -148,22 +145,6 @@ void init_done() { esp_schedule(); } -/* This is the entry point of the application. - * It gets called on the default stack, which grows down from the top - * of DRAM area. - * .bss has not been zeroed out yet, but .data and .rodata are in place. - * Cache is not enabled, so only ROM and IRAM functions can be called. - * Peripherals (except for SPI0 and UART0) are not initialized. - * This function does not return. - */ -extern "C" void ICACHE_RAM_ATTR app_entry(void) -{ - /* Allocate continuation context on this stack, and save pointer to it. */ - cont_t s_cont __attribute__((aligned(16))); - g_pcont = &s_cont; - /* Call the entry point of the SDK code. */ - call_user_start(); -} extern "C" void user_init(void) { struct rst_info *rtc_info_ptr = system_get_rst_info(); @@ -175,10 +156,10 @@ extern "C" void user_init(void) { initVariant(); - cont_init(g_pcont); + cont_init(&g_cont); ets_task(loop_task, - LOOP_TASK_PRIORITY, s_loop_queue, + LOOP_TASK_PRIORITY, g_loop_queue, LOOP_QUEUE_SIZE); system_init_done_cb(&init_done); diff --git a/cores/esp8266/core_esp8266_postmortem.c b/cores/esp8266/core_esp8266_postmortem.c index 3878cf1b9d..83976918a3 100644 --- a/cores/esp8266/core_esp8266_postmortem.c +++ b/cores/esp8266/core_esp8266_postmortem.c @@ -32,7 +32,7 @@ extern void __real_system_restart_local(); -extern cont_t* g_pcont; +extern cont_t g_cont; // These will be pointers to PROGMEM const strings static const char* s_panic_file = 0; @@ -131,8 +131,8 @@ void __wrap_system_restart_local() { ets_printf_P("\nSoft WDT reset\n"); } - uint32_t cont_stack_start = (uint32_t) &(g_pcont->stack); - uint32_t cont_stack_end = (uint32_t) g_pcont->stack_end; + uint32_t cont_stack_start = (uint32_t) &(g_cont.stack); + uint32_t cont_stack_end = (uint32_t) g_cont.stack_end; uint32_t stack_end; // amount of stack taken by interrupt or exception handler diff --git a/cores/esp8266/debug.h b/cores/esp8266/debug.h index 92d1356dce..346dcba0d8 100644 --- a/cores/esp8266/debug.h +++ b/cores/esp8266/debug.h @@ -22,8 +22,10 @@ void hexdump(const void *mem, uint32_t len, uint8_t cols); extern "C" { #endif +#include + void __panic_func(const char* file, int line, const char* func) __attribute__((noreturn)); -#define panic() __panic_func(__FILE__, __LINE__, __func__) +#define panic() __panic_func(PSTR(__FILE__), __LINE__, __func__) #ifdef __cplusplus } diff --git a/cores/esp8266/libc_replacements.c b/cores/esp8266/libc_replacements.c index fe111ba4cb..1d7c3f9f2d 100644 --- a/cores/esp8266/libc_replacements.c +++ b/cores/esp8266/libc_replacements.c @@ -122,7 +122,39 @@ void _exit(int status) { abort(); } -int atexit(void (*func)()) { - (void) func; - return 0; +#if 0 + +int ICACHE_RAM_ATTR printf(const char* format, ...) { + va_list arglist; + va_start(arglist, format); + int ret = ets_vprintf(ets_putc, format, arglist); + va_end(arglist); + return ret; +} + +int ICACHE_RAM_ATTR sprintf(char* buffer, const char* format, ...) { + int ret; + va_list arglist; + va_start(arglist, format); + ret = ets_vsprintf(buffer, format, arglist); + va_end(arglist); + return ret; +} + +int ICACHE_RAM_ATTR snprintf(char* buffer, size_t size, const char* format, ...) { + int ret; + va_list arglist; + va_start(arglist, format); + ret = ets_vsnprintf(buffer, size, format, arglist); + va_end(arglist); + return ret; +} + +int ICACHE_RAM_ATTR vprintf(const char * format, va_list arg) { + return ets_vprintf(ets_putc, format, arg); +} + +int ICACHE_RAM_ATTR vsnprintf(char * buffer, size_t size, const char * format, va_list arg) { + return ets_vsnprintf(buffer, size, format, arg); } +#endif diff --git a/cores/esp8266/spiffs_api.cpp b/cores/esp8266/spiffs_api.cpp index 390a6412fd..0bca9be8dc 100644 --- a/cores/esp8266/spiffs_api.cpp +++ b/cores/esp8266/spiffs_api.cpp @@ -25,7 +25,7 @@ using namespace fs; -FileImplPtr SPIFFSImpl::open(const char* path, OpenMode openMode, AccessMode accessMode) +FileImplPtr SPIFFSImpl::openFile(const char* path, OpenMode openMode, AccessMode accessMode) { if (!isSpiffsFilenameValid(path)) { DEBUGV("SPIFFSImpl::open: invalid path=`%s` \r\n", path); @@ -52,19 +52,20 @@ FileImplPtr SPIFFSImpl::open(const char* path, OpenMode openMode, AccessMode acc return std::make_shared(this, fd); } -bool SPIFFSImpl::exists(const char* path) +bool SPIFFSImpl::exists(const char* path) const { if (!isSpiffsFilenameValid(path)) { DEBUGV("SPIFFSImpl::exists: invalid path=`%s` \r\n", path); return false; } spiffs_stat stat; - int rc = SPIFFS_stat(&_fs, path, &stat); + int rc = SPIFFS_stat(const_cast(&_fs), path, &stat); return rc == SPIFFS_OK; } -DirImplPtr SPIFFSImpl::openDir(const char* path) +DirImplPtr SPIFFSImpl::openDir(const char* path, bool create) { + (void)create; if (strlen(path) > 0 && !isSpiffsFilenameValid(path)) { DEBUGV("SPIFFSImpl::openDir: invalid path=`%s` \r\n", path); return DirImplPtr(); diff --git a/cores/esp8266/spiffs_api.h b/cores/esp8266/spiffs_api.h index 4ce8d3e6ba..bee37ccbb2 100644 --- a/cores/esp8266/spiffs_api.h +++ b/cores/esp8266/spiffs_api.h @@ -58,9 +58,9 @@ class SPIFFSImpl : public FSImpl memset(&_fs, 0, sizeof(_fs)); } - FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) override; - bool exists(const char* path) override; - DirImplPtr openDir(const char* path) override; + FileImplPtr openFile(const char* path, OpenMode openMode, AccessMode accessMode) override; + bool exists(const char* path) const override; + DirImplPtr openDir(const char* path, bool create) override; bool rename(const char* pathFrom, const char* pathTo) override { @@ -80,7 +80,7 @@ class SPIFFSImpl : public FSImpl } return true; } - bool info(FSInfo& info) override + bool info(FSInfo& info) const override { info.maxOpenFiles = _maxOpenFds; info.blockSize = _blockSize; @@ -88,7 +88,7 @@ class SPIFFSImpl : public FSImpl info.maxOpenFiles = _maxOpenFds; info.maxPathLength = SPIFFS_OBJ_NAME_LEN; uint32_t totalBytes, usedBytes; - auto rc = SPIFFS_info(&_fs, &totalBytes, &usedBytes); + auto rc = SPIFFS_info(const_cast(&_fs), &totalBytes, &usedBytes); if (rc != SPIFFS_OK) { DEBUGV("SPIFFS_info: rc=%d, err=%d\r\n", rc, _fs.err_code); return false; @@ -165,6 +165,27 @@ class SPIFFSImpl : public FSImpl return true; } + bool isDir(const char* path) const override + { + (void)path; + // Not implemented + return false; + } + + size_t size(const char* path) const override + { + (void)path; + // Not implemented + return 0; + } + + time_t mtime(const char* path) const override + { + (void)path; + // Not implemented + return 0; + } + protected: friend class SPIFFSFileImpl; friend class SPIFFSDirImpl; @@ -247,7 +268,7 @@ class SPIFFSImpl : public FSImpl (void) report; (void) arg1; (void) arg2; - + // TODO: spiffs doesn't pass any context pointer along with _check_cb, // so we can't do anything useful here other than perhaps // feeding the watchdog @@ -351,6 +372,14 @@ class SPIFFSFileImpl : public FileImpl return result; } + bool truncate() override + { + CHECKFD(); + + // Not implemented + return false; + } + size_t size() const override { CHECKFD(); @@ -366,6 +395,7 @@ class SPIFFSFileImpl : public FileImpl SPIFFS_close(_fs->getFs(), _fd); DEBUGV("SPIFFS_close: fd=%d\r\n", _fd); + _fd = 0; } const char* name() const override @@ -375,6 +405,38 @@ class SPIFFSFileImpl : public FileImpl return (const char*) _stat.name; } + time_t mtime() const override + { + CHECKFD(); + + // Not implemented + return 0; + } + + bool remove() override + { + CHECKFD(); + + close(); + return _fs->remove((const char*)_stat.name); + } + + bool rename(const char *nameTo) override + { + CHECKFD(); + + close(); + // Not implemented + (void)nameTo; + /* + if (_fs->rename((const char*)_stat.name, nameTo)) { + strncpy((char*)_stat.name, nameTo, SPIFFS_OBJ_NAME_LEN); + return true; + } + */ + return false; + } + protected: void _getStat() const { @@ -402,6 +464,7 @@ class SPIFFSDirImpl : public DirImpl , _dir(dir) , _valid(false) { + memset(&_dirent, 0, sizeof(_dirent)); } ~SPIFFSDirImpl() override @@ -409,7 +472,31 @@ class SPIFFSDirImpl : public DirImpl SPIFFS_closedir(&_dir); } - FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) override + FileImplPtr openFile(const char* name, OpenMode openMode, + AccessMode accessMode) override + { + if (!_valid) { + return FileImplPtr(); + } + (void)name; + (void)openMode; + (void)accessMode; + // Not implemented + return FileImplPtr(); + } + + DirImplPtr openDir(const char* name, bool create) override + { + if (!_valid) { + return DirImplPtr(); + } + (void)name; + (void)create; + // Not implemented + return DirImplPtr(); + } + + FileImplPtr openEntryFile(OpenMode openMode, AccessMode accessMode) override { if (!_valid) { return FileImplPtr(); @@ -425,7 +512,77 @@ class SPIFFSDirImpl : public DirImpl return std::make_shared(_fs, fd); } - const char* fileName() override + DirImplPtr openEntryDir() override + { + if (!_valid) { + return DirImplPtr(); + } + // Not implemented + return DirImplPtr(); + } + + bool exists(const char* name) const override + { + if (!_valid) { + return false; + } + (void)name; + // Not implemented + return false; + } + + bool isDir(const char* name) const override + { + if (!_valid) { + return false; + } + (void)name; + // Not implemented + return false; + } + + size_t size(const char* name) const override + { + if (!_valid) { + return false; + } + (void)name; + // Not implemented + return 0; + } + + time_t mtime(const char* name) const override + { + if (!_valid) { + return false; + } + (void)name; + // Not implemented + return 0; + } + + bool remove(const char* name) override + { + if (!_valid) { + return false; + } + (void)name; + // Not implemented + return false; + } + + bool rename(const char *nameFrom, const char *nameTo) override + { + if (!_valid) { + return false; + } + (void)nameFrom; + (void)nameTo; + // Not implemented + return false; + } + + const char* entryName() const override { if (!_valid) { return nullptr; @@ -434,7 +591,7 @@ class SPIFFSDirImpl : public DirImpl return (const char*) _dirent.name; } - size_t fileSize() override + size_t entrySize() const override { if (!_valid) { return 0; @@ -443,8 +600,29 @@ class SPIFFSDirImpl : public DirImpl return _dirent.size; } - bool next() override + time_t entryMtime() const override + { + if (!_valid) { + return 0; + } + + // Not implemented + return 0; + } + + bool isEntryDir() const override + { + if (!_valid) { + return false; + } + + // Not implemented + return false; + } + + bool next(bool reset) override { + if (reset) memset(&_dirent, 0, sizeof(_dirent)); const int n = _pattern.length(); do { spiffs_dirent* result = SPIFFS_readdir(&_dir, &_dirent); @@ -453,6 +631,46 @@ class SPIFFSDirImpl : public DirImpl return _valid; } + bool removeEntry() override + { + if (!_valid) { + return false; + } + + // Not implemented + return false; + } + + bool renameEntry(const char *nameTo) override + { + if (!_valid) { + return false; + } + (void)nameTo; + // Not implemented + return false; + } + + time_t mtime() const override + { + if (!_valid) { + return 0; + } + + // Not implemented + return 0; + } + + const char* name() const override + { + if (!_valid) { + return nullptr; + } + + // Not implemented + return nullptr; + } + protected: String _pattern; SPIFFSImpl* _fs; diff --git a/cores/esp8266/umm_malloc/umm_malloc.c b/cores/esp8266/umm_malloc/umm_malloc.c index d65eac781d..472573adf1 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.c +++ b/cores/esp8266/umm_malloc/umm_malloc.c @@ -627,6 +627,7 @@ UMM_H_ATTPACKPRE typedef struct umm_block_t { # define umm_malloc malloc # define umm_calloc calloc # define umm_realloc realloc +# define umm_size msize #endif umm_block *umm_heap = NULL; @@ -857,7 +858,7 @@ static int check_poison_block( umm_block *pblock ) { pc_cur = pc + *((UMM_POISONED_BLOCK_LEN_TYPE *)pc) - UMM_POISON_SIZE_AFTER; if (!check_poison(pc_cur, UMM_POISON_SIZE_AFTER, "after")) { - printf("block start: %08x\n", pc + sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE); + printf("block start: %08x\n", pc + sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE); UMM_HEAP_CORRUPTION_CB(); ok = 0; goto clean; @@ -1649,6 +1650,47 @@ static void *_umm_realloc( void *ptr, size_t size ) { /* ------------------------------------------------------------------------ */ +static size_t _umm_size( void *ptr ) { + + unsigned short int blockSize; + + unsigned short int c; + + size_t curSize; + + if (umm_heap == NULL) { + umm_init(); + } + + if( ((void *)NULL == ptr) ) { + DBG_LOG_DEBUG( "size the NULL pointer = 0\n" ); + + return( 0 ); + } + + /* Protect the critical section... */ + UMM_CRITICAL_ENTRY(); + + /* Figure out which block we're in. Note the use of truncated division... */ + + c = (((char *)ptr)-(char *)(&(umm_heap[0])))/sizeof(umm_block); + + /* Figure out how big this block is... */ + + blockSize = (UMM_NBLOCK(c) - c); + + /* Figure out how many bytes are in this block */ + + curSize = (blockSize*sizeof(umm_block))-(sizeof(((umm_block *)0)->header)); + + /* Release the critical section... */ + UMM_CRITICAL_EXIT(); + + return( curSize ); +} + +/* ------------------------------------------------------------------------ */ + void *umm_malloc( size_t size ) { void *ret; @@ -1737,6 +1779,28 @@ void *umm_realloc( void *ptr, size_t size ) { /* ------------------------------------------------------------------------ */ +size_t umm_size( void *ptr ) { + size_t ret; + + ptr = GET_UNPOISONED(ptr); + + /* check poison of each blocks, if poisoning is enabled */ + if (!CHECK_POISON_ALL_BLOCKS()) { + return 0; + } + + /* check full integrity of the heap, if this check is enabled */ + if (!INTEGRITY_CHECK()) { + return 0; + } + + ret = _umm_size( ptr ); + + return ret; +} + +/* ------------------------------------------------------------------------ */ + void umm_free( void *ptr ) { ptr = GET_UNPOISONED(ptr); diff --git a/cores/esp8266/umm_malloc/umm_malloc.h b/cores/esp8266/umm_malloc/umm_malloc.h index 0019b0ec50..b39665a060 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.h +++ b/cores/esp8266/umm_malloc/umm_malloc.h @@ -38,6 +38,7 @@ void *umm_info( void *ptr, int force ); void *umm_malloc( size_t size ); void *umm_calloc( size_t num, size_t size ); void *umm_realloc( void *ptr, size_t size ); +size_t umm_size( void *ptr ); void umm_free( void *ptr ); size_t umm_free_heap_size( void ); diff --git a/cores/esp8266/umm_malloc/umm_malloc_cfg.h b/cores/esp8266/umm_malloc/umm_malloc_cfg.h index 314e51fbbc..044b1a397e 100644 --- a/cores/esp8266/umm_malloc/umm_malloc_cfg.h +++ b/cores/esp8266/umm_malloc/umm_malloc_cfg.h @@ -70,6 +70,7 @@ extern "C" { void *umm_malloc( size_t size ); void *umm_calloc( size_t num, size_t size ); void *umm_realloc( void *ptr, size_t size ); +#define umm_size msize #define umm_free free #define umm_zalloc(s) umm_calloc(1,s) diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index feada8c13b..68e0aefaa3 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -65,7 +65,7 @@ class StaticRequestHandler : public RequestHandler { , _path(path) , _cache_header(cache_header) { - _isFile = fs.exists(path); + _isFile = !fs.isDir(path); DEBUGV("StaticRequestHandler: path=%s uri=%s isFile=%d, cache_header=%s\r\n", path, uri, _isFile, cache_header); _baseUriLength = _uri.length(); } diff --git a/libraries/ESP8266WiFi/src/include/ClientContext.h b/libraries/ESP8266WiFi/src/include/ClientContext.h index eb8a286d6d..8affcc5829 100644 --- a/libraries/ESP8266WiFi/src/include/ClientContext.h +++ b/libraries/ESP8266WiFi/src/include/ClientContext.h @@ -487,9 +487,9 @@ class ClientContext _rx_buf_offset += size; } else if(!_rx_buf->next) { DEBUGV(":c0 %d, %d\r\n", size, _rx_buf->tot_len); - if(_pcb) { - tcp_recved(_pcb, _rx_buf->len); - } + //if(_pcb) { + // tcp_recved(_pcb, _rx_buf->len); + //} pbuf_free(_rx_buf); _rx_buf = 0; _rx_buf_offset = 0; @@ -499,9 +499,9 @@ class ClientContext _rx_buf = _rx_buf->next; _rx_buf_offset = 0; pbuf_ref(_rx_buf); - if(_pcb) { - tcp_recved(_pcb, head->len); - } + //if(_pcb) { + // tcp_recved(_pcb, head->len); + //} pbuf_free(head); } } @@ -519,9 +519,11 @@ class ClientContext if(_rx_buf) { DEBUGV(":rch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len); + tcp_recved(pcb, pb->tot_len); pbuf_cat(_rx_buf, pb); } else { DEBUGV(":rn %d\r\n", pb->tot_len); + tcp_recved(pcb, pb->tot_len); _rx_buf = pb; _rx_buf_offset = 0; } diff --git a/package.json b/package.json index 13dfbedf2a..4e152e25b1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "framework-arduinoespressif8266", - "description": "Arduino Wiring-based Framework (ESP8266 Core)", - "url": "https://github.com/esp8266/Arduino", + "name": "framework-arduinoespressif8266-adam5wu", + "description": "Arduino Wiring-based Framework (ESP8266 Core) [Adam5Wu Fork]", + "url": "https://github.com/Adam5Wu/Arduino-esp8266", "version": "2.5.0-dev" } diff --git a/package/build_boards_manager_package.sh b/package/build_boards_manager_package.sh index db847946df..1603439f4c 100755 --- a/package/build_boards_manager_package.sh +++ b/package/build_boards_manager_package.sh @@ -126,7 +126,7 @@ cat $srcdir/package/package_esp8266com_index.template.json | \ jq "$jq_arg" > package_esp8266com_index.json # Get previous release name -curl --silent https://api.github.com/repos/esp8266/Arduino/releases > releases.json +curl --silent https://api.github.com/repos/Adam5Wu/Arduino-esp8266/releases > releases.json # Previous final release (prerelase == false) prev_release=$(jq -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name' releases.json) # Previous release (possibly a pre-release) @@ -144,7 +144,7 @@ base_ver=$prev_any_release # Download previous release echo "Downloading base package: $base_ver" old_json=package_esp8266com_index_stable.json -curl -L -o $old_json "https://github.com/esp8266/Arduino/releases/download/${base_ver}/package_esp8266com_index.json" +curl -L -o $old_json "https://github.com/Adam5Wu/Arduino-esp8266/releases/download/${base_ver}/package_esp8266com_index.json" new_json=package_esp8266com_index.json set +e diff --git a/platform.txt b/platform.txt index e4de798c5b..86391bf7ee 100644 --- a/platform.txt +++ b/platform.txt @@ -37,10 +37,10 @@ compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implici compiler.S.cmd=xtensa-lx106-elf-gcc compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls -compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read +compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u call_user_start {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read compiler.c.elf.cmd=xtensa-lx106-elf-gcc -compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 -lstdc++ -lm -lc -lgcc +compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -laxtls -lbearssl -lespnow -lsmartconfig -lairkiss -lwpa2 -lstdc++ -lm -lc -lgcc compiler.cpp.cmd=xtensa-lx106-elf-g++ compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections diff --git a/tests/common.sh b/tests/common.sh index e76f24300a..4fb973a4bd 100755 --- a/tests/common.sh +++ b/tests/common.sh @@ -126,8 +126,8 @@ function run_host_tests() function build_package() { - export PKG_URL=https://github.com/esp8266/Arduino/releases/download/$TRAVIS_TAG/esp8266-$TRAVIS_TAG.zip - export DOC_URL=https://arduino-esp8266.readthedocs.io/en/$TRAVIS_TAG/ + export PKG_URL=https://github.com/Adam5Wu/Arduino-esp8266/releases/download/$TRAVIS_TAG/esp8266-$TRAVIS_TAG.zip + export DOC_URL=https://adam5wu-arduino-esp8266.readthedocs.io/en/$TRAVIS_TAG/ ./build_boards_manager_package.sh } @@ -146,8 +146,7 @@ function install_platformio() { pip install --user -U https://github.com/platformio/platformio/archive/develop.zip platformio platform install https://github.com/platformio/platform-espressif8266.git#feature/stage - sed -i 's/https:\/\/github\.com\/esp8266\/Arduino\.git/*/' ~/.platformio/platforms/espressif8266/platform.json - ln -s $TRAVIS_BUILD_DIR ~/.platformio/packages/framework-arduinoespressif8266 + sed -i "s:https\://github\.com/esp8266/Arduino\.git:file\://$TRAVIS_BUILD_DIR:" ~/.platformio/platforms/espressif8266/platform.json # Install dependencies: # - esp8266/examples/ConfigFile pio lib install ArduinoJson diff --git a/tests/host/fs/test_fs.cpp b/tests/host/fs/test_fs.cpp index 6e14af84f2..3859d61927 100644 --- a/tests/host/fs/test_fs.cpp +++ b/tests/host/fs/test_fs.cpp @@ -42,8 +42,8 @@ static std::set listDir (const char* path) std::set result; Dir dir = SPIFFS.openDir(path); while (dir.next()) { - REQUIRE(result.find(dir.fileName()) == std::end(result)); - result.insert(dir.fileName()); + REQUIRE(result.find(dir.entryName()) == std::end(result)); + result.insert(dir.entryName()); } return result; } diff --git a/tools/platformio-build.py b/tools/platformio-build.py index 2cc1efae65..19cd9db80d 100644 --- a/tools/platformio-build.py +++ b/tools/platformio-build.py @@ -88,8 +88,7 @@ def scons_patched_match_splitext(path, suffixes=None): LINKFLAGS=[ "-Wl,-wrap,system_restart_local", - "-Wl,-wrap,spi_flash_read", - "-u", "app_entry" + "-Wl,-wrap,spi_flash_read" ] ) diff --git a/tools/sdk/include/ets_sys.h b/tools/sdk/include/ets_sys.h index 731e562b4f..c4bb25990d 100644 --- a/tools/sdk/include/ets_sys.h +++ b/tools/sdk/include/ets_sys.h @@ -215,7 +215,6 @@ int ets_vprintf(int (*print_function)(int), const char * format, va_list arg) __ int ets_putc(int); bool ets_task(ETSTask task, uint8 prio, ETSEvent *queue, uint8 qlen); bool ets_post(uint8 prio, ETSSignal sig, ETSParam par); -void ets_update_cpu_frequency(uint32_t ticks_per_us); #ifdef __cplusplus diff --git a/tools/sdk/include/user_interface.h b/tools/sdk/include/user_interface.h index 4d12133b1e..6e84e08029 100644 --- a/tools/sdk/include/user_interface.h +++ b/tools/sdk/include/user_interface.h @@ -251,6 +251,7 @@ struct station_config { // with both ssid[] and bssid[] matched. Please check about this. uint8 bssid[6]; wifi_fast_scan_threshold_t threshold; + bool open_and_wep_mode_disable; }; bool wifi_station_get_config(struct station_config *config); diff --git a/tools/sdk/ld/eagle.app.v6.common.ld.h b/tools/sdk/ld/eagle.app.v6.common.ld.h index 0d46fdc241..006bef592a 100644 --- a/tools/sdk/ld/eagle.app.v6.common.ld.h +++ b/tools/sdk/ld/eagle.app.v6.common.ld.h @@ -12,7 +12,7 @@ PHDRS /* Default entry point: */ -ENTRY(app_entry) +ENTRY(call_user_start) EXTERN(_DebugExceptionVector) EXTERN(_DoubleExceptionVector) EXTERN(_KernelExceptionVector) @@ -84,11 +84,6 @@ SECTIONS _data_end = ABSOLUTE(.); } >dram0_0_seg :dram0_0_phdr - .noinit : ALIGN(4) - { - *(.noinit) - } >dram0_0_seg :dram0_0_phdr - #ifdef VTABLES_IN_DRAM #include "eagle.app.v6.common.ld.vtables.h" #endif @@ -113,6 +108,7 @@ SECTIONS *liblwip2.a:(.literal .text .literal.* .text.*) *liblwip2_1460.a:(.literal .text .literal.* .text.*) *libaxtls.a:(.literal .text .literal.* .text.*) + *libbearssl.a:(.literal .text .literal.* .text.*) *libat.a:(.literal.* .text.*) *libcrypto.a:(.literal.* .text.*) *libespnow.a:(.literal.* .text.*) diff --git a/tools/sdk/lib/libat.a b/tools/sdk/lib/libat.a index 7567719117..49852aca23 100644 Binary files a/tools/sdk/lib/libat.a and b/tools/sdk/lib/libat.a differ diff --git a/tools/sdk/lib/libbearssl.a b/tools/sdk/lib/libbearssl.a new file mode 100644 index 0000000000..f1509264d3 Binary files /dev/null and b/tools/sdk/lib/libbearssl.a differ diff --git a/tools/sdk/lib/libcrypto.a b/tools/sdk/lib/libcrypto.a index 1c3feaba43..7156634c74 100644 Binary files a/tools/sdk/lib/libcrypto.a and b/tools/sdk/lib/libcrypto.a differ diff --git a/tools/sdk/lib/libgcc.a b/tools/sdk/lib/libgcc.a index beb9274848..121b28d4ab 100644 Binary files a/tools/sdk/lib/libgcc.a and b/tools/sdk/lib/libgcc.a differ diff --git a/tools/sdk/lib/liblwip.a b/tools/sdk/lib/liblwip.a index e77e304d77..e3a3ad3e1a 100644 Binary files a/tools/sdk/lib/liblwip.a and b/tools/sdk/lib/liblwip.a differ diff --git a/tools/sdk/lib/libmain.a b/tools/sdk/lib/libmain.a index c0e70cafef..fc64bd207c 100644 Binary files a/tools/sdk/lib/libmain.a and b/tools/sdk/lib/libmain.a differ diff --git a/tools/sdk/lib/libnet80211.a b/tools/sdk/lib/libnet80211.a index d3ecbd68a9..c30ddef3d3 100644 Binary files a/tools/sdk/lib/libnet80211.a and b/tools/sdk/lib/libnet80211.a differ diff --git a/tools/sdk/lib/libpp.a b/tools/sdk/lib/libpp.a index 6135231c79..b3789cc3df 100644 Binary files a/tools/sdk/lib/libpp.a and b/tools/sdk/lib/libpp.a differ diff --git a/tools/sdk/lib/libwpa.a b/tools/sdk/lib/libwpa.a index 7ea69a61f4..11bb8536b4 100644 Binary files a/tools/sdk/lib/libwpa.a and b/tools/sdk/lib/libwpa.a differ diff --git a/tools/sdk/lib/libwps.a b/tools/sdk/lib/libwps.a index 0c3503350a..11150681b1 100644 Binary files a/tools/sdk/lib/libwps.a and b/tools/sdk/lib/libwps.a differ diff --git a/tools/sdk/lwip/include/lwip/app/espconn_buf.h b/tools/sdk/lwip/include/lwip/app/espconn_buf.h index 8bdfaa12ab..326f181fad 100644 --- a/tools/sdk/lwip/include/lwip/app/espconn_buf.h +++ b/tools/sdk/lwip/include/lwip/app/espconn_buf.h @@ -23,15 +23,15 @@ typedef struct ringbuf_t { uint8_t *buf; uint8_t *head, *tail; size_t size; -} ringbuf, *ringbuf_t; +} ringbuf, *_ringbuf_t; -ringbuf_t ringbuf_new(size_t capacity); +_ringbuf_t ringbuf_new(size_t capacity); size_t ringbuf_buffer_size(const struct ringbuf_t *rb); -void ringbuf_reset(ringbuf_t rb); +void ringbuf_reset(_ringbuf_t rb); -void ringbuf_free(ringbuf_t *rb); +void ringbuf_free(_ringbuf_t *rb); size_t ringbuf_capacity(const struct ringbuf_t *rb); @@ -47,14 +47,14 @@ const void* ringbuf_tail(const struct ringbuf_t *rb); const void* ringbuf_head(const struct ringbuf_t *rb); -static uint8_t *ringbuf_nextp(ringbuf_t rb, const uint8_t *p); +static uint8_t *ringbuf_nextp(_ringbuf_t rb, const uint8_t *p); size_t ringbuf_findchr(const struct ringbuf_t *rb, int c, size_t offset); -size_t ringbuf_memset(ringbuf_t dst, int c, size_t len); +size_t ringbuf_memset(_ringbuf_t dst, int c, size_t len); -void *ringbuf_memcpy_into(ringbuf_t dst, const void *src, size_t count); +void *ringbuf_memcpy_into(_ringbuf_t dst, const void *src, size_t count); -void *ringbuf_memcpy_from(void *dst, ringbuf_t src, size_t count); +void *ringbuf_memcpy_from(void *dst, _ringbuf_t src, size_t count); #endif /* RINGBUF_H_ */ diff --git a/tools/sdk/lwip/src/app/espconn_buf.c b/tools/sdk/lwip/src/app/espconn_buf.c index f91d1d23ea..90d955a20b 100644 --- a/tools/sdk/lwip/src/app/espconn_buf.c +++ b/tools/sdk/lwip/src/app/espconn_buf.c @@ -20,11 +20,11 @@ static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__; #define lwIP_unlikely(Expression) !!(Expression) #endif -#define lwIP_ASSERT(Expression) do{if(!(Expression)) {os_printf("%s %d\n", __func__, __LINE__);return;}}while(0) +#define lwIP_ASSERT(Expression) do{if(!(Expression)) {os_printf("%s %d\n", __func__, __LINE__);break;}}while(0) -ringbuf_t ringbuf_new(size_t capacity) +_ringbuf_t ringbuf_new(size_t capacity) { - ringbuf_t rb = (ringbuf_t)os_zalloc(sizeof(struct ringbuf_t)); + _ringbuf_t rb = (_ringbuf_t)os_zalloc(sizeof(struct ringbuf_t)); if (rb){ rb->size = capacity + 1; rb->buf = (uint8*)os_zalloc(rb->size); @@ -43,12 +43,12 @@ size_t ringbuf_buffer_size(const struct ringbuf_t *rb) return rb->size; } -void ringbuf_reset(ringbuf_t rb) +void ringbuf_reset(_ringbuf_t rb) { rb ->head = rb->tail = rb->buf; } -void ringbuf_free(ringbuf_t *rb) +void ringbuf_free(_ringbuf_t *rb) { lwIP_ASSERT(rb && *rb); os_free((*rb)->buf); @@ -99,7 +99,7 @@ const void* ringbuf_head(const struct ringbuf_t *rb) return rb->head; } -static uint8_t *ringbuf_nextp(ringbuf_t rb, const uint8_t *p) +static uint8_t *ringbuf_nextp(_ringbuf_t rb, const uint8_t *p) { lwIP_ASSERT((p >= rb->buf) && (p < ringbuf_end(rb))); return rb->buf + ((++p -rb->buf) % ringbuf_buffer_size(rb)); @@ -122,7 +122,7 @@ size_t ringbuf_findchr(const struct ringbuf_t *rb, int c, size_t offset) return ringbuf_findchr(rb, c, offset + n); } -size_t ringbuf_memset(ringbuf_t dst, int c, size_t len) +size_t ringbuf_memset(_ringbuf_t dst, int c, size_t len) { const uint8_t *bufend = ringbuf_end(dst); size_t nwritten = 0; @@ -149,7 +149,7 @@ size_t ringbuf_memset(ringbuf_t dst, int c, size_t len) return nwritten; } -void *ringbuf_memcpy_into(ringbuf_t dst,const void *src, size_t count) +void *ringbuf_memcpy_into(_ringbuf_t dst, const void *src, size_t count) { const uint8_t *u8src = src; const uint8_t *bufend = ringbuf_end(dst); @@ -175,7 +175,7 @@ void *ringbuf_memcpy_into(ringbuf_t dst,const void *src, size_t count) return dst->head; } -void *ringbuf_memcpy_from(void *dst,ringbuf_t src, size_t count) +void *ringbuf_memcpy_from(void *dst, _ringbuf_t src, size_t count) { size_t bytes_used = ringbuf_bytes_used(src); diff --git a/tools/sdk/lwip/src/core/udp.c b/tools/sdk/lwip/src/core/udp.c index 42539d6d77..0d84f0e2a2 100644 --- a/tools/sdk/lwip/src/core/udp.c +++ b/tools/sdk/lwip/src/core/udp.c @@ -726,7 +726,12 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) u8_t rebind; LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = ")); - ip_addr_debug_print(UDP_DEBUG, ipaddr); + if (ip_addr_isany(ipaddr)) + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("")); + else if (ipaddr->addr == IPADDR_BROADCAST) + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("")); + else + ip_addr_debug_print(UDP_DEBUG, ipaddr); LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port)); rebind = 0;