├── .gitignore ├── Makefile ├── README.md ├── build_mkspiffs ├── components ├── mkspiffs │ ├── .gitignore │ ├── .gitmodules │ ├── LICENSE.txt │ ├── Makefile │ ├── README.md │ ├── include │ │ ├── sdkconfig.h │ │ └── spiffs_config.h │ ├── main.cpp │ ├── spiffs │ │ ├── .travis.yml │ │ ├── FUZZING.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── afltests │ │ │ ├── 100 │ │ │ ├── 200 │ │ │ ├── a │ │ │ └── b │ │ ├── docs │ │ │ ├── TECH_SPEC │ │ │ └── TODO │ │ ├── files.mk │ │ ├── makefile │ │ └── src │ │ │ ├── default │ │ │ └── spiffs_config.h │ │ │ ├── spiffs.h │ │ │ ├── spiffs_cache.c │ │ │ ├── spiffs_check.c │ │ │ ├── spiffs_gc.c │ │ │ ├── spiffs_hydrogen.c │ │ │ ├── spiffs_nucleus.c │ │ │ ├── spiffs_nucleus.h │ │ │ └── test │ │ │ ├── main.c │ │ │ ├── params_test.h │ │ │ ├── test_bugreports.c │ │ │ ├── test_check.c │ │ │ ├── test_dev.c │ │ │ ├── test_hydrogen.c │ │ │ ├── test_spiffs.c │ │ │ ├── test_spiffs.h │ │ │ ├── testrunner.c │ │ │ ├── testrunner.h │ │ │ └── testsuites.c │ └── tclap │ │ ├── Arg.h │ │ ├── ArgException.h │ │ ├── ArgTraits.h │ │ ├── COPYING │ │ ├── CmdLine.h │ │ ├── CmdLineInterface.h │ │ ├── CmdLineOutput.h │ │ ├── Constraint.h │ │ ├── DocBookOutput.h │ │ ├── HelpVisitor.h │ │ ├── IgnoreRestVisitor.h │ │ ├── MultiArg.h │ │ ├── MultiSwitchArg.h │ │ ├── OptionalUnlabeledTracker.h │ │ ├── StandardTraits.h │ │ ├── StdOutput.h │ │ ├── SwitchArg.h │ │ ├── UnlabeledMultiArg.h │ │ ├── UnlabeledValueArg.h │ │ ├── ValueArg.h │ │ ├── ValuesConstraint.h │ │ ├── VersionVisitor.h │ │ ├── Visitor.h │ │ ├── XorHandler.h │ │ └── ZshCompletionOutput.h ├── spiffs │ ├── Kconfig │ ├── component.mk │ ├── esp_spiffs.c │ ├── include │ │ ├── esp_spiffs.h │ │ └── spiffs_config.h │ ├── spiffs │ │ ├── .travis.yml │ │ ├── FUZZING.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── afltests │ │ │ ├── 100 │ │ │ ├── 200 │ │ │ ├── a │ │ │ └── b │ │ ├── docs │ │ │ ├── TECH_SPEC │ │ │ └── TODO │ │ ├── files.mk │ │ ├── makefile │ │ └── src │ │ │ ├── default │ │ │ └── spiffs_config.h │ │ │ ├── spiffs.h │ │ │ ├── spiffs_cache.c │ │ │ ├── spiffs_check.c │ │ │ ├── spiffs_gc.c │ │ │ ├── spiffs_hydrogen.c │ │ │ ├── spiffs_nucleus.c │ │ │ ├── spiffs_nucleus.h │ │ │ └── test │ │ │ ├── main.c │ │ │ ├── params_test.h │ │ │ ├── test_bugreports.c │ │ │ ├── test_check.c │ │ │ ├── test_dev.c │ │ │ ├── test_hydrogen.c │ │ │ ├── test_spiffs.c │ │ │ ├── test_spiffs.h │ │ │ ├── testrunner.c │ │ │ ├── testrunner.h │ │ │ └── testsuites.c │ └── test │ │ ├── component.mk │ │ └── test_spiffs.c └── spiffs_image │ ├── Makefile.projbuild │ ├── component.mk │ ├── image │ ├── images │ │ ├── test │ │ │ └── test3.jpg │ │ ├── test1.jpg │ │ ├── test2.jpg │ │ └── test4.jpg │ └── spiffs.info │ ├── spiffs_image.img │ ├── spiffs_param.mk │ └── spiffs_part_info.py ├── main ├── Kconfig.projbuild ├── component.mk └── testSpiffs.c ├── partitions_example.csv └── sdkconfig.defaults /.gitignore: -------------------------------------------------------------------------------- 1 | .config 2 | *.o 3 | *.pyc 4 | *.a 5 | *.d 6 | 7 | # gtags 8 | GTAGS 9 | GRTAGS 10 | GPATH 11 | 12 | # emacs 13 | .dir-locals.el 14 | 15 | # emacs temp file suffixes 16 | *~ 17 | .#* 18 | \#*# 19 | 20 | sdkconfig 21 | sdkconfig.old 22 | sdkconfig.lobo 23 | .cproject 24 | .project 25 | BUILD 26 | 27 | .settings/ 28 | 29 | build/ 30 | temp/ 31 | *.dis 32 | *.elf 33 | *.map 34 | **/.DS_Store 35 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := testSpiffs 7 | 8 | include $(IDF_PATH)/make/project.mk 9 | -------------------------------------------------------------------------------- /build_mkspiffs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ########################################################## 4 | # To build 'mkspiffs' run with no espressif tools path set ! 5 | # ########################################################## 6 | 7 | if [ ! -f build/include/sdkconfig.h ]; then 8 | echo "'sdkconfig.h' not found, build your firmware first" 9 | exit 1 10 | fi 11 | 12 | grep "CONFIG_SPIFFS_" build/include/sdkconfig.h > components/mkspiffs/include/sdkconfig.h 13 | make -C components/mkspiffs clean 14 | make -C components/mkspiffs 15 | -------------------------------------------------------------------------------- /components/mkspiffs/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | mkspiffs 3 | mkspiffs.exe 4 | out.* 5 | *.tar.gz 6 | 7 | # eclipse wokspace files and dirs 8 | .project 9 | .cproject 10 | .settings 11 | -------------------------------------------------------------------------------- /components/mkspiffs/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "spiffs"] 2 | path = spiffs 3 | url = https://github.com/pellepl/spiffs.git 4 | -------------------------------------------------------------------------------- /components/mkspiffs/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2017 Ivan Grokhotkov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /components/mkspiffs/Makefile: -------------------------------------------------------------------------------- 1 | BUILD_CONFIG_NAME ?= 2 | 3 | ifeq ($(OS),Windows_NT) 4 | TARGET_OS := WINDOWS 5 | DIST_SUFFIX := windows 6 | ARCHIVE_CMD := 7z a 7 | ARCHIVE_EXTENSION := zip 8 | TARGET := mkspiffs.exe 9 | TARGET_CFLAGS := -mno-ms-bitfields 10 | TARGET_LDFLAGS := -Wl,-static -static-libgcc 11 | CC=gcc 12 | CXX=g++ 13 | else 14 | UNAME_S := $(shell uname -s) 15 | ifeq ($(UNAME_S),Linux) 16 | TARGET_OS := LINUX 17 | UNAME_P := $(shell uname -p) 18 | ifeq ($(UNAME_P),x86_64) 19 | DIST_SUFFIX := linux64 20 | endif 21 | ifneq ($(filter %86,$(UNAME_P)),) 22 | DIST_SUFFIX := linux32 23 | endif 24 | endif 25 | ifeq ($(UNAME_S),Darwin) 26 | TARGET_OS := OSX 27 | DIST_SUFFIX := osx 28 | CC=clang 29 | CXX=clang++ 30 | TARGET_CFLAGS = -mmacosx-version-min=10.7 -arch i386 -arch x86_64 31 | TARGET_CXXFLAGS = -mmacosx-version-min=10.7 -arch i386 -arch x86_64 -stdlib=libc++ 32 | TARGET_LDFLAGS = -arch i386 -arch x86_64 -stdlib=libc++ 33 | endif 34 | ARCHIVE_CMD := tar czf 35 | ARCHIVE_EXTENSION := tar.gz 36 | TARGET := mkspiffs 37 | endif 38 | 39 | VERSION ?= $(shell git describe --always) 40 | 41 | OBJ := main.o \ 42 | spiffs/src/spiffs_cache.o \ 43 | spiffs/src/spiffs_check.o \ 44 | spiffs/src/spiffs_gc.o \ 45 | spiffs/src/spiffs_hydrogen.o \ 46 | spiffs/src/spiffs_nucleus.o \ 47 | 48 | INCLUDES := -Itclap -Iinclude -Ispiffs/src -I. 49 | 50 | override CFLAGS := -std=gnu99 -Os -Wall $(TARGET_CFLAGS) $(CFLAGS) 51 | override CXXFLAGS := -std=gnu++11 -Os -Wall $(TARGET_CXXFLAGS) $(CXXFLAGS) 52 | override LDFLAGS := $(TARGET_LDFLAGS) $(LDFLAGS) 53 | override CPPFLAGS := $(INCLUDES) -D$(TARGET_OS) -DVERSION=\"$(VERSION)\" -D__NO_INLINE__ $(CPPFLAGS) 54 | 55 | DIST_NAME := mkspiffs-$(VERSION)$(BUILD_CONFIG_NAME)-$(DIST_SUFFIX) 56 | DIST_DIR := $(DIST_NAME) 57 | DIST_ARCHIVE := $(DIST_NAME).$(ARCHIVE_EXTENSION) 58 | 59 | .PHONY: all clean dist 60 | 61 | all: $(TARGET) 62 | 63 | dist: test $(DIST_ARCHIVE) 64 | 65 | $(DIST_ARCHIVE): $(TARGET) $(DIST_DIR) 66 | cp $(TARGET) $(DIST_DIR)/ 67 | $(ARCHIVE_CMD) $(DIST_ARCHIVE) $(DIST_DIR) 68 | 69 | $(TARGET): $(OBJ) 70 | $(CXX) $^ -o $@ $(LDFLAGS) 71 | strip $(TARGET) 72 | 73 | $(DIST_DIR): 74 | @mkdir -p $@ 75 | 76 | clean: 77 | @rm -f $(TARGET) $(OBJ) 78 | 79 | SPIFFS_TEST_FS_CONFIG := -s 0x100000 -p 512 -b 0x2000 80 | 81 | test: $(TARGET) 82 | mkdir -p spiffs_t 83 | cp spiffs/src/*.h spiffs_t/ 84 | cp spiffs/src/*.c spiffs_t/ 85 | rm -rf spiffs_t/.git 86 | rm -f spiffs_t/.DS_Store 87 | ls -1 spiffs_t > out.list0 88 | touch spiffs_t/.DS_Store 89 | mkdir -p spiffs_t/.git 90 | touch spiffs_t/.git/foo 91 | ./mkspiffs -c spiffs_t $(SPIFFS_TEST_FS_CONFIG) out.spiffs_t | sort | sed s/^\\/// > out.list1 92 | ./mkspiffs -u spiffs_u $(SPIFFS_TEST_FS_CONFIG) out.spiffs_t | sort | sed s/^\\/// > out.list_u 93 | ./mkspiffs -l $(SPIFFS_TEST_FS_CONFIG) out.spiffs_t | cut -f 2 | sort | sed s/^\\/// > out.list2 94 | diff --strip-trailing-cr out.list0 out.list1 95 | diff --strip-trailing-cr out.list0 out.list2 96 | rm -rf spiffs_t/.git 97 | rm -f spiffs_t/.DS_Store 98 | diff spiffs_t spiffs_u 99 | rm -f out.{list0,list1,list2,list_u,spiffs_t} 100 | rm -R spiffs_u spiffs_t 101 | -------------------------------------------------------------------------------- /components/mkspiffs/README.md: -------------------------------------------------------------------------------- 1 | # mkspiffs 2 | Tool to build and unpack [SPIFFS](https://github.com/pellepl/spiffs) images. 3 | 4 | ## **IMPORTANT** - building for ESP32 esp-idf spiffs 5 | --- 6 | The **sdkconfig.h** from your application using spiffs has to be used in build process! 7 | Before building **mkspiffs**, copy the **sdkconfig.h** from your application **build/include** directory to **mkspiffs/include** 8 | After every change to spiffs configuration **rebuild mkspiffs** 9 | 10 | 11 | ## Usage 12 | 13 | ``` 14 | 15 | mkspiffs {-c |-u |-l|-i} [-d <0-5>] [-b ] 16 | [-p ] [-s ] [--] [--version] [-h] 17 | 18 | 19 | 20 | Where: 21 | 22 | -c , --create 23 | (OR required) create spiffs image from a directory 24 | -- OR -- 25 | -u , --unpack 26 | (OR required) unpack spiffs image to a directory 27 | -- OR -- 28 | -l, --list 29 | (OR required) list files in spiffs image 30 | -- OR -- 31 | -i, --visualize 32 | (OR required) visualize spiffs image 33 | 34 | 35 | -d <0-5>, --debug <0-5> 36 | Debug level. 0 means no debug output. 37 | 38 | -b , --block 39 | fs block size, in bytes 40 | 41 | -p , --page 42 | fs page size, in bytes 43 | 44 | -s , --size 45 | fs image size, in bytes 46 | 47 | --, --ignore_rest 48 | Ignores the rest of the labeled arguments following this flag. 49 | 50 | --version 51 | Displays version information and exits. 52 | 53 | -h, --help 54 | Displays usage information and exits. 55 | 56 | 57 | (required) spiffs image file 58 | 59 | 60 | ``` 61 | ## Build 62 | 63 | You need gcc (≥4.8) or clang(≥600.0.57), and make. On Windows, use MinGW. 64 | 65 | Run: 66 | ```bash 67 | $ make dist 68 | ``` 69 | 70 | ### Build status 71 | 72 | Linux | Windows 73 | ------|------- 74 | [![Linux build status](http://img.shields.io/travis/igrr/mkspiffs.svg)](https://travis-ci.org/igrr/mkspiffs) | [![Windows build status](http://img.shields.io/appveyor/ci/igrr/mkspiffs.svg)](https://ci.appveyor.com/project/igrr/mkspiffs) 75 | 76 | 77 | ## License 78 | 79 | MIT 80 | 81 | ## To do 82 | 83 | - [ ] Add more debug output and print SPIFFS debug output 84 | - [ ] Error handling 85 | - [ ] Determine the image size automatically when opening a file 86 | - [ ] Code cleanup 87 | -------------------------------------------------------------------------------- /components/mkspiffs/include/sdkconfig.h: -------------------------------------------------------------------------------- 1 | #define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 2 | #define CONFIG_SPIFFS_CACHE_WR 1 3 | #define CONFIG_SPIFFS_CACHE 1 4 | #define CONFIG_SPIFFS_USE_DIR 1 5 | #define CONFIG_SPIFFS_META_LENGTH 5 6 | #define CONFIG_SPIFFS_USE_MAGIC 1 7 | #define CONFIG_SPIFFS_PAGE_CHECK 1 8 | #define CONFIG_SPIFFS_USE_MTIME 1 9 | #define CONFIG_SPIFFS_GC_MAX_RUNS 10 10 | #define CONFIG_SPIFFS_MAX_PARTITIONS 3 11 | #define CONFIG_SPIFFS_OBJ_NAME_LEN 32 12 | #define CONFIG_SPIFFS_PAGE_SIZE 256 13 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | compiler: 4 | - gcc 5 | 6 | before_script: 7 | 8 | script: make all && make clean && make test && make build-all && make clean test FLAGS=-DSPIFFS_OBJ_META_LEN=8 9 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/FUZZING.md: -------------------------------------------------------------------------------- 1 | # Fuzzing SPIFFS 2 | 3 | The SPIFFS test suite includes a test program designed for fuzzing with 4 | [AFL](http://lcamtuf.coredump.cx/afl/). This automatically exercises the 5 | SPIFFS API and verifies that the file system does not crash or interact incorrectly 6 | with the flash chip. 7 | 8 | There are two steps to fuzzing. The first is to build the test suite with 9 | the AFL version of gcc. The CC variable should point to your copy of afl-gcc. 10 | 11 | ``` 12 | make clean test CC=/usr/local/bin/afl-gcc 13 | ``` 14 | 15 | There is a new test `afl_test` that reads from stdin a list of commands 16 | and arguments. These are interpreted and executed on the API. The `afltests` 17 | directory contains a number of test cases that can be fed to the `afl_test` test. 18 | 19 | 20 | The second is to run this test suite under afl as follows (where findings is 21 | the output directory): 22 | 23 | ``` 24 | afl-fuzz -i afltests -o findings ./build/linux_spiffs_test -f afl_test 25 | ``` 26 | 27 | This run will take hours (or days) and will (hopefully) not find any crashes. 28 | If a crash (or hang) is found, then the input file that caused the crash is 29 | saved. This allows the specific test case to be debugged. 30 | 31 | ## Reducing the size of the file 32 | 33 | AFL comes with `afl-tmin` which can reduce the size of the test input file to 34 | make it easier to debug. 35 | 36 | ``` 37 | afl-tmin -i findings/crashes/ -o smalltest -- build/linux_spiffs_test -f afl_test 38 | ``` 39 | 40 | This will write a short version of the testcase file to `smalltest`. This can then be 41 | fed into the test program for debugging: 42 | 43 | ``` 44 | build/linux_spiffs_test -f afl_test < smalltest 45 | ``` 46 | 47 | This should still crash, but allows it to be run under a debugger. 48 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2017 Peter Andersson (pelleplutt1976gmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/README.md: -------------------------------------------------------------------------------- 1 | # SPIFFS (SPI Flash File System) 2 | **V0.3.7** 3 | 4 | [![Build Status](https://travis-ci.org/pellepl/spiffs.svg?branch=master)](https://travis-ci.org/pellepl/spiffs) 5 | 6 | Copyright (c) 2013-2017 Peter Andersson (pelleplutt1976 at gmail.com) 7 | 8 | For legal stuff, see [LICENSE](https://github.com/pellepl/spiffs/blob/master/LICENSE). Basically, you may do whatever you want with the source. Use, modify, sell, print it out, roll it and smoke it - as long as I won't be held responsible. 9 | 10 | Love to hear feedback though! 11 | 12 | 13 | ## INTRODUCTION 14 | 15 | Spiffs is a file system intended for SPI NOR flash devices on embedded targets. 16 | 17 | Spiffs is designed with following characteristics in mind: 18 | - Small (embedded) targets, sparse RAM without heap 19 | - Only big areas of data (blocks) can be erased 20 | - An erase will reset all bits in block to ones 21 | - Writing pulls one to zeroes 22 | - Zeroes can only be pulled to ones by erase 23 | - Wear leveling 24 | 25 | 26 | ## BUILDING 27 | 28 | `mkdir build; make` 29 | 30 | Otherwise, configure the `builddir` variable towards the top of `makefile` as something opposed to the default `build`. Sanity check on the host via `make test` and refer to `.travis.yml` for the official in-depth testing procedure. See the wiki for [integrating](https://github.com/pellepl/spiffs/wiki/Integrate-spiffs) spiffs into projects and [spiffsimg](https://github.com/nodemcu/nodemcu-firmware/tree/master/tools/spiffsimg) from [nodemcu](https://github.com/nodemcu) is a good example on the subject. 31 | 32 | 33 | ## FEATURES 34 | 35 | What spiffs does: 36 | - Specifically designed for low ram usage 37 | - Uses statically sized ram buffers, independent of number of files 38 | - Posix-like api: open, close, read, write, seek, stat, etc 39 | - It can run on any NOR flash, not only SPI flash - theoretically also on embedded flash of a microprocessor 40 | - Multiple spiffs configurations can run on same target - and even on same SPI flash device 41 | - Implements static wear leveling 42 | - Built in file system consistency checks 43 | - Highly configurable 44 | 45 | What spiffs does not: 46 | - Presently, spiffs does not support directories. It produces a flat structure. Creating a file with path *tmp/myfile.txt* will create a file called *tmp/myfile.txt* instead of a *myfile.txt* under directory *tmp*. 47 | - It is not a realtime stack. One write operation might last much longer than another. 48 | - Poor scalability. Spiffs is intended for small memory devices - the normal sizes for SPI flashes. Going beyond ~128Mbyte is probably a bad idea. This is a side effect of the design goal to use as little ram as possible. 49 | - Presently, it does not detect or handle bad blocks. 50 | - One configuration, one binary. There's no generic spiffs binary that handles all types of configurations. 51 | 52 | 53 | ## MORE INFO 54 | 55 | See the [wiki](https://github.com/pellepl/spiffs/wiki) for [configuring](https://github.com/pellepl/spiffs/wiki/Configure-spiffs), [integrating](https://github.com/pellepl/spiffs/wiki/Integrate-spiffs), [using](https://github.com/pellepl/spiffs/wiki/Using-spiffs), and [optimizing](https://github.com/pellepl/spiffs/wiki/Performance-and-Optimizing) spiffs. 56 | 57 | For design, see [docs/TECH_SPEC](https://github.com/pellepl/spiffs/blob/master/docs/TECH_SPEC). 58 | 59 | For a generic spi flash driver, see [this](https://github.com/pellepl/spiflash_driver). 60 | 61 | ## HISTORY 62 | 63 | ### 0.3.7 64 | - fixed prevent seeking to negative offsets #158 65 | - fixed file descriptor offsets not updated for multiple fds on same file #157 66 | - fixed cache page not closed for removed files #156 67 | - fixed a lseek bug when seeking exactly to end of a fully indexed first level LUT #148 68 | - fixed wear leveling issue #145 69 | - fixed attempt to write out of bounds in flash #130, 70 | - set file offset when seeking over end #121 (thanks @sensslen) 71 | - fixed seeking in virgin files #120 (thanks @sensslen) 72 | - Optional file metadata #128 (thanks @cesanta) 73 | - AFL testing framework #100 #143 (thanks @pjsg) 74 | - Testframe updates 75 | 76 | New API functions: 77 | - `SPIFFS_update_meta, SPIFFS_fupdate_meta` - updates metadata for a file 78 | 79 | New config defines: 80 | - `SPIFFS_OBJ_META_LEN` - enable possibility to add extra metadata to files 81 | 82 | ### 0.3.6 83 | - Fix range bug in index memory mapping #98 84 | - Add index memory mapping #97 85 | - Optimize SPIFFS_read for large files #96 86 | - Add temporal cache for opening files #95 87 | - More robust gc #93 (thanks @dismirlian) 88 | - Fixed a double write of same data in certain cache situations 89 | - Fixed an open bug in READ_ONLY builds 90 | - File not visible in SPIFFS_readdir #90 (thanks @benpicco-tmp) 91 | - Cache load code cleanup #92 (thanks @niclash) 92 | - Fixed lock/unlock asymmetry #88 #87 (thanks @JackJefferson, @dpruessner) 93 | - Testframe updates 94 | 95 | New API functions: 96 | - `SPIFFS_ix_map` - map index meta data to memory for a file 97 | - `SPIFFS_ix_unmap` - unmaps index meta data for a file 98 | - `SPIFFS_ix_remap` - changes file offset for index metadata map 99 | - `SPIFFS_bytes_to_ix_map_entries` - utility, get length of needed vector for given amount of bytes 100 | - `SPIFFS_ix_map_entries_to_bytes` - utility, get number of bytes a vector can represent given length 101 | 102 | New config defines: 103 | - `SPIFFS_IX_MAP` - enable possibility to map index meta data to memory for reading faster 104 | - `SPIFFS_TEMPORAL_FD_CACHE` - enable temporal cache for opening files faster 105 | - `SPIFFS_TEMPORAL_CACHE_HIT_SCORE` - for tuning the temporal cache 106 | 107 | ### 0.3.5 108 | - Fixed a bug in fs check 109 | - API returns actual error codes #84) (thanks @Nails) 110 | - Fix compiler warnings for non-gcc #83 #81 (thanks @Nails) 111 | - Unable to recover from full fs #82 (thanks @rojer) 112 | - Define SPIFFS_O_* flags #80 113 | - Problem with long filenames #79 (thanks @psjg) 114 | - Duplicate file name bug fix #74 (thanks @igrr) 115 | - SPIFFS_eof and SPIFFS_tell return wrong value #72 (thanks @ArtemPisarenko) 116 | - Bunch of testframe updates #77 #78 #86 (thanks @dpreussner, @psjg a.o) 117 | 118 | ### 0.3.4 119 | - Added user callback file func. 120 | - Fixed a stat bug with obj id. 121 | - SPIFFS_probe_fs added 122 | - Add possibility to compile a read-only version of spiffs 123 | - Make magic dependent on fs length, if needed (see #59 & #66) (thanks @hreintke) 124 | - Exposed SPIFFS_open_by_page_function 125 | - Zero-size file cannot be seek #57 (thanks @lishen2) 126 | - Add tell and eof functions #54 (thanks @raburton) 127 | - Make api string params const #53 (thanks @raburton) 128 | - Preserve user_data during mount() #51 (thanks @rojer) 129 | 130 | New API functions: 131 | - `SPIFFS_set_file_callback_func` - register a callback informing about file events 132 | - `SPIFFS_probe_fs` - probe a spi flash trying to figure out size of fs 133 | - `SPIFFS_open_by_page` - open a file by page index 134 | - `SPIFFS_eof` - checks if end of file is reached 135 | - `SPIFFS_tell` - returns current file offset 136 | 137 | New config defines: 138 | - `SPIFFS_READ_ONLY` 139 | - `SPIFFS_USE_MAGIC_LENGTH` 140 | 141 | ### 0.3.3 142 | **Might not be compatible with 0.3.2 structures. See issue #40** 143 | - Possibility to add integer offset to file handles 144 | - Truncate function presumes too few free pages #49 145 | - Bug in truncate function #48 (thanks @PawelDefee) 146 | - Update spiffs_gc.c - remove unnecessary parameter (thanks @PawelDefee) 147 | - Update INTEGRATION docs (thanks @PawelDefee) 148 | - Fix pointer truncation in 64-bit platforms (thanks @igrr) 149 | - Zero-sized files cannot be read #44 (thanks @rojer) 150 | - (More) correct calculation of max_id in obj_lu_find #42 #41 (thanks @lishen2) 151 | - Check correct error code in obj_lu_find_free #41 (thanks @lishen2) 152 | - Moar comments for SPIFFS_lseek (thanks @igrr) 153 | - Fixed padding in spiffs_page_object_ix #40 (thanks @jmattsson @lishen2) 154 | - Fixed gc_quick test (thanks @jmattsson) 155 | - Add SPIFFS_EXCL flag #36 156 | - SPIFFS_close may fail silently if cache is enabled #37 157 | - User data in callbacks #34 158 | - Ignoring SINGLETON build in cache setup (thanks Luca) 159 | - Compilation error fixed #32 (thanks @chotasanjiv) 160 | - Align cand_scores (thanks @hefloryd) 161 | - Fix build warnings when SPIFFS_CACHE is 0 (thanks @ajaybhargav) 162 | 163 | New config defines: 164 | - `SPIFFS_FILEHDL_OFFSET` 165 | 166 | ### 0.3.2 167 | - Limit cache size if too much cache is given (thanks pgeiem) 168 | - New feature - Controlled erase. #23 169 | - SPIFFS_rename leaks file descriptors #28 (thanks benpicco) 170 | - moved dbg print defines in test framework to params_test.h 171 | - lseek should return the resulting offset (thanks hefloryd) 172 | - fixed type on dbg ifdefs 173 | - silence warning about signed/unsigned comparison when spiffs_obj_id is 32 bit (thanks benpicco) 174 | - Possible error in test_spiffs.c #21 (thanks yihcdaso-yeskela) 175 | - Cache might writethrough too often #16 176 | - even moar testrunner updates 177 | - Test framework update and some added tests 178 | - Some thoughts for next gen 179 | - Test sigsevs when having too many sectors #13 (thanks alonewolfx2) 180 | - GC might be suboptimal #11 181 | - Fix eternal readdir when objheader at last block, last entry 182 | 183 | New API functions: 184 | - `SPIFFS_gc_quick` - call a nonintrusive gc 185 | - `SPIFFS_gc` - call a full-scale intrusive gc 186 | 187 | ### 0.3.1 188 | - Removed two return warnings, was too triggerhappy on release 189 | 190 | ### 0.3.0 191 | - Added existing namecheck when creating files 192 | - Lots of static analysis bugs #6 193 | - Added rename func 194 | - Fix SPIFFS_read length when reading beyond file size 195 | - Added reading beyond file length testcase 196 | - Made build a bit more configurable 197 | - Changed name in spiffs from "errno" to "err_code" due to conflicts compiling in mingw 198 | - Improved GC checks, fixed an append bug, more robust truncate for very special case 199 | - GC checks preempts GC, truncate even less picky 200 | - Struct alignment needed for some targets, define in spiffs config #10 201 | - Spiffs filesystem magic, definable in config 202 | 203 | New config defines: 204 | - `SPIFFS_USE_MAGIC` - enable or disable magic check upon mount 205 | - `SPIFFS_ALIGNED_OBJECT_INDEX_TABLES` - alignment for certain targets 206 | 207 | New API functions: 208 | - `SPIFFS_rename` - rename files 209 | - `SPIFFS_clearerr` - clears last errno 210 | - `SPIFFS_info` - returns info on used and total bytes in fs 211 | - `SPIFFS_format` - formats the filesystem 212 | - `SPIFFS_mounted` - checks if filesystem is mounted 213 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/afltests/100: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loboris/ESP32_spiffs_example/fc883eab6cec212c6de21c488cee4285fbb32a4c/components/mkspiffs/spiffs/afltests/100 -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/afltests/200: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loboris/ESP32_spiffs_example/fc883eab6cec212c6de21c488cee4285fbb32a4c/components/mkspiffs/spiffs/afltests/200 -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/afltests/a: -------------------------------------------------------------------------------- 1 | b55 2 | O4W4R4C4D4 3 | b45 4 | d5rh 5 | O4W4R4f4C4 6 | baaU 7 | d5rh 8 | OaWaRafaCa 9 | cd5rh 10 | OaWaRafaCa 11 | O4S4W4R4C4 12 | d5rh 13 | O4W4S4R4C4 14 | d5rh 15 | O4W4R4S4C4 16 | d5rh 17 | O4W4R4C4 18 | d5rh 19 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/afltests/b: -------------------------------------------------------------------------------- 1 | b55 2 | O4 3 | W?W?W?W?W?f4 4 | WW:W;f4 5 | C4 6 | b45 7 | d5rh 8 | O4W?R4f4C4 9 | baa 10 | d5rh 11 | OaWaRafaCa 12 | d5rh 13 | OaWaRafaCa 14 | O4W?R4C4 15 | d5rh 16 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/docs/TODO: -------------------------------------------------------------------------------- 1 | * When mending lost pages, also see if they fit into length specified in object index header 2 | 3 | SPIFFS2 thoughts 4 | 5 | * Instead of exact object id:s in the object lookup tables, use a hash of span index and object id. 6 | Eg. object id xor:ed with bit-reversed span index. 7 | This should decrease number of actual pages that needs to be visited when looking thru the obj lut. 8 | 9 | * Logical number of each block. When moving stuff in a garbage collected page, the free 10 | page is assigned the same number as the garbage collected. Thus, object index pages do not have to 11 | be rewritten. 12 | 13 | * Steal one page, use as a bit parity page. When starting an fs modification operation, write one bit 14 | as zero. When ending, write another bit as zero. On mount, if number of zeroes in page is uneven, a 15 | check is automatically run. -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/files.mk: -------------------------------------------------------------------------------- 1 | ifndef spiffs 2 | $(warn defaulting path to generic spiffs module, spiffs variable not set) 3 | spiffs = ../generic/spiffs 4 | endif 5 | FLAGS += -DCONFIG_BUILD_SPIFFS 6 | INC += -I${spiffs}/src 7 | CPATH += ${spiffs}/src 8 | CFILES += spiffs_nucleus.c 9 | CFILES += spiffs_gc.c 10 | CFILES += spiffs_hydrogen.c 11 | CFILES += spiffs_cache.c 12 | CFILES += spiffs_check.c 13 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/makefile: -------------------------------------------------------------------------------- 1 | BINARY = linux_spiffs_test 2 | 3 | ############ 4 | # 5 | # Paths 6 | # 7 | ############ 8 | 9 | sourcedir = src 10 | builddir = build 11 | 12 | 13 | ############# 14 | # 15 | # Build tools 16 | # 17 | ############# 18 | 19 | CC ?= gcc 20 | LD ?= ld 21 | GDB ?= gdb 22 | OBJCOPY ?= objcopy 23 | OBJDUMP ?= objdump 24 | MKDIR ?= mkdir -p 25 | 26 | ############### 27 | # 28 | # Files and libs 29 | # 30 | ############### 31 | 32 | NO_TEST ?= 0 33 | CFLAGS = $(FLAGS) 34 | ifeq (1, $(strip $(NO_TEST))) 35 | CFILES_TEST = main.c 36 | CFLAGS += -DNO_TEST -Werror 37 | else 38 | CFILES_TEST = main.c \ 39 | test_spiffs.c \ 40 | test_dev.c \ 41 | test_check.c \ 42 | test_hydrogen.c \ 43 | test_bugreports.c \ 44 | testsuites.c \ 45 | testrunner.c 46 | CFLAGS += -D_SPIFFS_TEST 47 | endif 48 | include files.mk 49 | INCLUDE_DIRECTIVES = -I./${sourcedir} -I./${sourcedir}/default -I./${sourcedir}/test 50 | COMPILEROPTIONS = $(INCLUDE_DIRECTIVES) 51 | 52 | COMPILEROPTIONS_APP = $(INCLUDE_DIRECTIVES) \ 53 | -Wall -Wno-format-y2k -W -Wstrict-prototypes -Wmissing-prototypes \ 54 | -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch \ 55 | -Wshadow -Wcast-align -Wchar-subscripts -Winline -Wnested-externs\ 56 | -Wredundant-decls 57 | 58 | ############ 59 | # 60 | # Tasks 61 | # 62 | ############ 63 | 64 | vpath %.c ${sourcedir} ${sourcedir}/default ${sourcedir}/test 65 | 66 | OBJFILES = $(CFILES:%.c=${builddir}/%.o) 67 | OBJFILES_TEST = $(CFILES_TEST:%.c=${builddir}/%.o) 68 | 69 | DEPFILES = $(CFILES:%.c=${builddir}/%.d) $(CFILES_TEST:%.c=${builddir}/%.d) 70 | 71 | ALLOBJFILES += $(OBJFILES) $(OBJFILES_TEST) 72 | 73 | DEPENDENCIES = $(DEPFILES) 74 | 75 | # link object files, create binary 76 | $(BINARY): $(ALLOBJFILES) 77 | @echo "... linking" 78 | @${CC} $(LINKEROPTIONS) -o ${builddir}/$(BINARY) $(ALLOBJFILES) $(LIBS) 79 | ifeq (1, $(strip $(NO_TEST))) 80 | @echo "size: `du -b ${builddir}/${BINARY} | sed 's/\([0-9]*\).*/\1/g '` bytes" 81 | endif 82 | 83 | 84 | -include $(DEPENDENCIES) 85 | 86 | # compile c files 87 | $(OBJFILES) : ${builddir}/%.o:%.c 88 | @echo "... compile $@" 89 | @${CC} $(COMPILEROPTIONS_APP) $(CFLAGS) -g -c -o $@ $< 90 | 91 | $(OBJFILES_TEST) : ${builddir}/%.o:%.c 92 | @echo "... compile $@" 93 | @${CC} ${COMPILEROPTIONS} $(CFLAGS) -g -c -o $@ $< 94 | 95 | # make dependencies 96 | # @echo "... depend $@"; 97 | $(DEPFILES) : ${builddir}/%.d:%.c 98 | @rm -f $@; \ 99 | ${CC} $(COMPILEROPTIONS) -M $< > $@.$$$$; \ 100 | sed 's,\($*\)\.o[ :]*, ${builddir}/\1.o $@ : ,g' < $@.$$$$ > $@; \ 101 | rm -f $@.$$$$ 102 | 103 | all: mkdirs $(BINARY) 104 | 105 | mkdirs: 106 | -@${MKDIR} ${builddir} 107 | -@${MKDIR} test_data 108 | 109 | FILTER ?= 110 | 111 | test: $(BINARY) 112 | ifdef $(FILTER) 113 | ./build/$(BINARY) 114 | else 115 | ./build/$(BINARY) -f $(FILTER) 116 | endif 117 | 118 | test_failed: $(BINARY) 119 | ./build/$(BINARY) _tests_fail 120 | 121 | clean: 122 | @echo ... removing build files in ${builddir} 123 | @rm -f ${builddir}/*.o 124 | @rm -f ${builddir}/*.d 125 | @rm -f ${builddir}/*.elf 126 | 127 | ONOFF = 1 0 128 | OFFON = 0 1 129 | build-all: 130 | @for rdonly in $(ONOFF); do \ 131 | for singleton in $(ONOFF); do \ 132 | for hal_cb_xtra in $(OFFON); do \ 133 | for cache in $(OFFON); do \ 134 | for magic in $(OFFON); do \ 135 | for temporal_cache in $(OFFON); do \ 136 | for ix_map in $(OFFON); do \ 137 | echo; \ 138 | echo ============================================================; \ 139 | echo SPIFFS_READ_ONLY=$$rdonly; \ 140 | echo SPIFFS_SINGLETON=$$singleton; \ 141 | echo SPIFFS_HAL_CALLBACK_EXTRA=$$hal_cb_xtra; \ 142 | echo SPIFFS_CACHE, SPIFFS_CACHE_WR=$$cache; \ 143 | echo SPIFFS_USE_MAGIC, SPIFFS_USE_MAGIC_LENGTH=$$magic; \ 144 | echo SPIFFS_TEMPORAL_FD_CACHE=$$temporal_cache; \ 145 | echo SPIFFS_IX_MAP=$$ix_map; \ 146 | $(MAKE) clean && $(MAKE) FLAGS="\ 147 | -DSPIFFS_HAL_CALLBACK_EXTRA=$$hal_cb_xtra \ 148 | -DSPIFFS_SINGLETON=$$singleton \ 149 | -DSPIFFS_CACHE=$$cache \ 150 | -DSPIFFS_CACHE_WR=$$cache \ 151 | -DSPIFFS_READ_ONLY=$$rdonly \ 152 | -DSPIFFS_USE_MAGIC=$$magic \ 153 | -DSPIFFS_USE_MAGIC_LENGTH=$$magic \ 154 | -DSPIFFS_TEMPORAL_FD_CACHE=$$temporal_cache \ 155 | -DSPIFFS_IX_MAP=$$ix_map \ 156 | " NO_TEST=1; \ 157 | done || exit 1; \ 158 | done \ 159 | done \ 160 | done \ 161 | done \ 162 | done \ 163 | done 164 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/src/test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef NO_TEST 4 | #include "testrunner.h" 5 | #endif 6 | 7 | int main(int argc, char **args) { 8 | #ifndef NO_TEST 9 | run_tests(argc, args); 10 | #endif 11 | exit(EXIT_SUCCESS); 12 | } 13 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/src/test/params_test.h: -------------------------------------------------------------------------------- 1 | /* 2 | * params_test.h 3 | * 4 | * Created on: May 26, 2013 5 | * Author: petera 6 | */ 7 | 8 | #ifndef PARAMS_TEST_H_ 9 | #define PARAMS_TEST_H_ 10 | 11 | //////////////// TEST PARAMS //////////////// 12 | 13 | // default test total emulated spi flash size 14 | #define PHYS_FLASH_SIZE (16*1024*1024) 15 | // default test spiffs file system size 16 | #define SPIFFS_FLASH_SIZE (2*1024*1024) 17 | // default test spiffs file system offset in emulated spi flash 18 | #define SPIFFS_PHYS_ADDR (4*1024*1024) 19 | // default test sector size 20 | #define SECTOR_SIZE 65536 21 | // default test logical block size 22 | #define LOG_BLOCK (SECTOR_SIZE*2) 23 | // default test logical page size 24 | #define LOG_PAGE (SECTOR_SIZE/256) 25 | // default test number of filedescs 26 | #define DEFAULT_NUM_FD 16 27 | // default test number of cache pages 28 | #define DEFAULT_NUM_CACHE_PAGES 8 29 | 30 | // When testing, test bench create reference files for comparison on 31 | // the actual hard drive. By default, put these on ram drive for speed. 32 | #define TEST_PATH "/dev/shm/spiffs/test-data/" 33 | 34 | #define ASSERT(c, m) real_assert((c),(m), __FILE__, __LINE__); 35 | void real_assert(int c, const char *n, const char *file, int l); 36 | 37 | /////////// SPIFFS BUILD CONFIG //////////// 38 | 39 | // test using filesystem magic 40 | #ifndef SPIFFS_USE_MAGIC 41 | #define SPIFFS_USE_MAGIC 1 42 | #endif 43 | // test using filesystem magic length 44 | #ifndef SPIFFS_USE_MAGIC_LENGTH 45 | #define SPIFFS_USE_MAGIC_LENGTH 1 46 | #endif 47 | // test using extra param in callback 48 | #ifndef SPIFFS_HAL_CALLBACK_EXTRA 49 | #define SPIFFS_HAL_CALLBACK_EXTRA 1 50 | #endif 51 | // test using filehandle offset 52 | #ifndef SPIFFS_FILEHDL_OFFSET 53 | #define SPIFFS_FILEHDL_OFFSET 1 54 | // use this offset 55 | #define TEST_SPIFFS_FILEHDL_OFFSET 0x1000 56 | #endif 57 | 58 | #ifdef NO_TEST 59 | #define SPIFFS_LOCK(fs) 60 | #define SPIFFS_UNLOCK(fs) 61 | #else 62 | struct spiffs_t; 63 | extern void test_lock(struct spiffs_t *fs); 64 | extern void test_unlock(struct spiffs_t *fs); 65 | #define SPIFFS_LOCK(fs) test_lock(fs) 66 | #define SPIFFS_UNLOCK(fs) test_unlock(fs) 67 | #endif 68 | 69 | // dbg output 70 | #define SPIFFS_DBG(_f, ...) //printf("\x1b[32m" _f "\x1b[0m", ## __VA_ARGS__) 71 | #define SPIFFS_API_DBG(_f, ...) //printf("\n\x1b[1m\x1b[7m" _f "\x1b[0m", ## __VA_ARGS__) 72 | #define SPIFFS_GC_DBG(_f, ...) //printf("\x1b[36m" _f "\x1b[0m", ## __VA_ARGS__) 73 | #define SPIFFS_CACHE_DBG(_f, ...) //printf("\x1b[33m" _f "\x1b[0m", ## __VA_ARGS__) 74 | #define SPIFFS_CHECK_DBG(_f, ...) //printf("\x1b[31m" _f "\x1b[0m", ## __VA_ARGS__) 75 | 76 | // needed types 77 | typedef signed int s32_t; 78 | typedef unsigned int u32_t; 79 | typedef signed short s16_t; 80 | typedef unsigned short u16_t; 81 | typedef signed char s8_t; 82 | typedef unsigned char u8_t; 83 | 84 | #endif /* PARAMS_TEST_H_ */ 85 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/src/test/test_dev.c: -------------------------------------------------------------------------------- 1 | /* 2 | * test_dev.c 3 | * 4 | * Created on: Jul 14, 2013 5 | * Author: petera 6 | */ 7 | 8 | 9 | #include "testrunner.h" 10 | #include "test_spiffs.h" 11 | #include "spiffs_nucleus.h" 12 | #include "spiffs.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | SUITE(dev_tests) 21 | static void setup() { 22 | _setup(); 23 | } 24 | static void teardown() { 25 | _teardown(); 26 | } 27 | 28 | TEST(interrupted_write) { 29 | char *name = "interrupt"; 30 | char *name2 = "interrupt2"; 31 | int res; 32 | spiffs_file fd; 33 | 34 | const u32_t sz = SPIFFS_CFG_LOG_PAGE_SZ(FS)*8; 35 | u8_t *buf = malloc(sz); 36 | memrand(buf, sz); 37 | 38 | printf(" create reference file\n"); 39 | fd = SPIFFS_open(FS, name, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); 40 | TEST_CHECK(fd > 0); 41 | clear_flash_ops_log(); 42 | res = SPIFFS_write(FS, fd, buf, sz); 43 | TEST_CHECK(res >= 0); 44 | SPIFFS_close(FS, fd); 45 | 46 | u32_t written = get_flash_ops_log_write_bytes(); 47 | printf(" written bytes: %i\n", written); 48 | 49 | 50 | printf(" create error file\n"); 51 | fd = SPIFFS_open(FS, name2, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); 52 | TEST_CHECK(fd > 0); 53 | clear_flash_ops_log(); 54 | invoke_error_after_write_bytes(written/2, 0); 55 | res = SPIFFS_write(FS, fd, buf, sz); 56 | SPIFFS_close(FS, fd); 57 | TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_TEST); 58 | 59 | clear_flash_ops_log(); 60 | 61 | #if SPIFFS_CACHE 62 | // delete all cache 63 | spiffs_cache *cache = spiffs_get_cache(FS); 64 | cache->cpage_use_map = 0; 65 | #endif 66 | 67 | 68 | printf(" read error file\n"); 69 | fd = SPIFFS_open(FS, name2, SPIFFS_RDONLY, 0); 70 | TEST_CHECK(fd > 0); 71 | 72 | spiffs_stat s; 73 | res = SPIFFS_fstat(FS, fd, &s); 74 | TEST_CHECK(res >= 0); 75 | printf(" file size: %i\n", s.size); 76 | 77 | if (s.size > 0) { 78 | u8_t *buf2 = malloc(s.size); 79 | res = SPIFFS_read(FS, fd, buf2, s.size); 80 | TEST_CHECK(res >= 0); 81 | 82 | u32_t ix = 0; 83 | for (ix = 0; ix < s.size; ix += 16) { 84 | int i; 85 | printf(" "); 86 | for (i = 0; i < 16; i++) { 87 | printf("%02x", buf[ix+i]); 88 | } 89 | printf(" "); 90 | for (i = 0; i < 16; i++) { 91 | printf("%02x", buf2[ix+i]); 92 | } 93 | printf("\n"); 94 | } 95 | free(buf2); 96 | } 97 | SPIFFS_close(FS, fd); 98 | 99 | 100 | printf(" FS check\n"); 101 | SPIFFS_check(FS); 102 | 103 | printf(" read error file again\n"); 104 | fd = SPIFFS_open(FS, name2, SPIFFS_APPEND | SPIFFS_RDWR, 0); 105 | TEST_CHECK(fd > 0); 106 | res = SPIFFS_fstat(FS, fd, &s); 107 | TEST_CHECK(res >= 0); 108 | printf(" file size: %i\n", s.size); 109 | printf(" write file\n"); 110 | res = SPIFFS_write(FS, fd, buf, sz); 111 | TEST_CHECK(res >= 0); 112 | SPIFFS_close(FS, fd); 113 | 114 | free(buf); 115 | 116 | return TEST_RES_OK; 117 | 118 | } TEST_END 119 | 120 | SUITE_TESTS(dev_tests) 121 | ADD_TEST(interrupted_write) 122 | SUITE_END(dev_tests) 123 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/src/test/test_spiffs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * test_spiffs.h 3 | * 4 | * Created on: Jun 19, 2013 5 | * Author: petera 6 | */ 7 | 8 | #ifndef TEST_SPIFFS_H_ 9 | #define TEST_SPIFFS_H_ 10 | 11 | #include "spiffs.h" 12 | 13 | #define FS &__fs 14 | 15 | extern spiffs __fs; 16 | 17 | 18 | #define CHECK(r) if (!(r)) return -1; 19 | #define CHECK_RES(r) if (r < 0) return -1; 20 | #define FS_PURE_DATA_PAGES(fs) \ 21 | (SPIFFS_CFG_PHYS_SZ(fs) / SPIFFS_CFG_LOG_PAGE_SZ(fs)- (fs)->block_count * SPIFFS_OBJ_LOOKUP_PAGES(fs)) 22 | #define FS_PURE_DATA_SIZE(fs) \ 23 | FS_PURE_DATA_PAGES(fs) * SPIFFS_DATA_PAGE_SIZE(fs) 24 | 25 | typedef enum { 26 | EMPTY, 27 | SMALL, 28 | MEDIUM, 29 | LARGE, 30 | } tfile_size; 31 | 32 | typedef enum { 33 | UNTAMPERED, 34 | APPENDED, 35 | MODIFIED, 36 | REWRITTEN, 37 | } tfile_type; 38 | 39 | typedef enum { 40 | SHORT = 3, 41 | NORMAL = 15, 42 | LONG = 100, 43 | } tfile_life; 44 | 45 | typedef struct { 46 | tfile_size tsize; 47 | tfile_type ttype; 48 | tfile_life tlife; 49 | } tfile_conf; 50 | 51 | typedef struct { 52 | int state; 53 | spiffs_file fd; 54 | tfile_conf cfg; 55 | char name[32]; 56 | } tfile; 57 | 58 | void fs_reset(); 59 | void fs_reset_specific(u32_t addr_offset, u32_t phys_addr, u32_t phys_size, 60 | u32_t phys_sector_size, 61 | u32_t log_block_size, u32_t log_page_size); 62 | s32_t fs_mount_specific(u32_t phys_addr, u32_t phys_size, 63 | u32_t phys_sector_size, 64 | u32_t log_block_size, u32_t log_page_size); 65 | void fs_mount_dump(char *fname, 66 | u32_t addr_offset, u32_t phys_addr, u32_t phys_size, 67 | u32_t phys_sector_size, 68 | u32_t log_block_size, u32_t log_page_size); 69 | 70 | void fs_store_dump(char *fname); 71 | void fs_load_dump(char *fname); 72 | 73 | void fs_set_addr_offset(u32_t offset); 74 | int read_and_verify(char *name); 75 | int read_and_verify_fd(spiffs_file fd, char *name); 76 | void dump_page(spiffs *fs, spiffs_page_ix p); 77 | void hexdump(u32_t addr, u32_t len); 78 | char *make_test_fname(const char *name); 79 | void clear_test_path(); 80 | void area_write(u32_t addr, u8_t *buf, u32_t size); 81 | void area_set(u32_t addr, u8_t d, u32_t size); 82 | void area_read(u32_t addr, u8_t *buf, u32_t size); 83 | void dump_erase_counts(spiffs *fs); 84 | void dump_flash_access_stats(); 85 | void set_flash_ops_log(int enable); 86 | void clear_flash_ops_log(); 87 | u32_t get_flash_ops_log_read_bytes(); 88 | u32_t get_flash_ops_log_write_bytes(); 89 | void invoke_error_after_read_bytes(u32_t b, char once_only); 90 | void invoke_error_after_write_bytes(u32_t b, char once_only); 91 | void fs_set_validate_flashing(int i); 92 | int get_error_count(); 93 | int count_taken_fds(spiffs *fs); 94 | 95 | void memrand(u8_t *b, int len); 96 | int test_create_file(char *name); 97 | int test_create_and_write_file(char *name, int size, int chunk_size); 98 | u32_t get_spiffs_file_crc_by_fd(spiffs_file fd); 99 | u32_t get_spiffs_file_crc(char *name); 100 | void _setup(); 101 | void _setup_test_only(); 102 | void _teardown(); 103 | u32_t tfile_get_size(tfile_size s); 104 | int run_file_config(int cfg_count, tfile_conf* cfgs, int max_runs, int max_concurrent_files, int dbg); 105 | 106 | void test_lock(spiffs *fs); 107 | void test_unlock(spiffs *fs); 108 | 109 | #endif /* TEST_SPIFFS_H_ */ 110 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/src/test/testrunner.c: -------------------------------------------------------------------------------- 1 | /* 2 | * testrunner.c 3 | * 4 | * Created on: Jun 18, 2013 5 | * Author: petera 6 | */ 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "testrunner.h" 20 | 21 | static struct { 22 | test *tests; 23 | test *_last_test; 24 | int test_count; 25 | void (*on_stop)(test *t); 26 | test_res *failed; 27 | test_res *failed_last; 28 | test_res *stopped; 29 | test_res *stopped_last; 30 | FILE *spec; 31 | char incl_filter[256]; 32 | char excl_filter[256]; 33 | } test_main; 34 | 35 | void test_init(void (*on_stop)(test *t)) { 36 | test_main.on_stop = on_stop; 37 | } 38 | 39 | static int abort_on_error = 0; 40 | static int error_count = 0; 41 | 42 | static char check_spec(char *name) { 43 | if (test_main.spec) { 44 | fseek(test_main.spec, 0, SEEK_SET); 45 | char *line = NULL; 46 | size_t sz; 47 | ssize_t read; 48 | while ((read = getline(&line, &sz, test_main.spec)) != -1) { 49 | if (strncmp(line, name, strlen(line)-1) == 0) { 50 | free(line); 51 | return 1; 52 | } 53 | } 54 | free(line); 55 | return 0; 56 | } else { 57 | return 1; 58 | } 59 | } 60 | 61 | static char check_incl_filter(char *name) { 62 | if (strlen(test_main.incl_filter)== 0) return 1; 63 | return strstr(name, test_main.incl_filter) == 0 ? 0 : 2; 64 | } 65 | 66 | static char check_excl_filter(char *name) { 67 | if (strlen(test_main.excl_filter)== 0) return 1; 68 | return strstr(name, test_main.excl_filter) == 0 ? 1 : 0; 69 | } 70 | 71 | void _add_test(test_f f, char *name, void (*setup)(test *t), void (*teardown)(test *t), int non_default) { 72 | if (f == 0) return; 73 | if (!check_spec(name)) return; 74 | if (check_incl_filter(name) <= non_default) return; 75 | if (!check_excl_filter(name)) return; 76 | DBGT("adding test %s\n", name); 77 | test *t = malloc(sizeof(test)); 78 | memset(t, 0, sizeof(test)); 79 | t->f = f; 80 | strcpy(t->name, name); 81 | t->setup = setup; 82 | t->teardown = teardown; 83 | if (test_main.tests == 0) { 84 | test_main.tests = t; 85 | } else { 86 | test_main._last_test->_next = t; 87 | } 88 | test_main._last_test = t; 89 | test_main.test_count++; 90 | } 91 | 92 | static void add_res(test *t, test_res **head, test_res **last) { 93 | test_res *tr = malloc(sizeof(test_res)); 94 | memset(tr,0,sizeof(test_res)); 95 | strcpy(tr->name, t->name); 96 | if (*head == 0) { 97 | *head = tr; 98 | } else { 99 | (*last)->_next = tr; 100 | } 101 | *last = tr; 102 | } 103 | 104 | static void dump_res(test_res **head) { 105 | test_res *tr = (*head); 106 | while (tr) { 107 | test_res *next_tr = tr->_next; 108 | printf(" %s\n", tr->name); 109 | free(tr); 110 | tr = next_tr; 111 | } 112 | } 113 | 114 | int get_error_count(void) { 115 | return error_count; 116 | } 117 | 118 | void inc_error_count(void) { 119 | error_count++; 120 | } 121 | 122 | int set_abort_on_error(int val) { 123 | int old_val = abort_on_error; 124 | abort_on_error = val; 125 | 126 | return old_val; 127 | } 128 | 129 | int get_abort_on_error(void) { 130 | return abort_on_error; 131 | } 132 | 133 | int run_tests(int argc, char **args) { 134 | memset(&test_main, 0, sizeof(test_main)); 135 | int arg; 136 | int incl_filter = 0; 137 | int excl_filter = 0; 138 | for (arg = 1; arg < argc; arg++) { 139 | if (strlen(args[arg]) == 0) continue; 140 | if (0 == strcmp("-f", args[arg])) { 141 | incl_filter = 1; 142 | continue; 143 | } 144 | if (0 == strcmp("-e", args[arg])) { 145 | excl_filter = 1; 146 | continue; 147 | } 148 | if (incl_filter) { 149 | strcpy(test_main.incl_filter, args[arg]); 150 | incl_filter = 0; 151 | } else if (excl_filter) { 152 | strcpy(test_main.excl_filter, args[arg]); 153 | excl_filter = 0; 154 | } else { 155 | printf("running tests from %s\n", args[arg]); 156 | FILE *fd = fopen(args[1], "r"); 157 | if (fd == NULL) { 158 | printf("%s not found\n", args[arg]); 159 | return -2; 160 | } 161 | test_main.spec = fd; 162 | } 163 | } 164 | 165 | DBGT("adding suites...\n"); 166 | add_suites(); 167 | DBGT("%i tests added\n", test_main.test_count); 168 | if (test_main.spec) { 169 | fclose(test_main.spec); 170 | } 171 | 172 | if (test_main.test_count == 0) { 173 | printf("No tests to run\n"); 174 | return 0; 175 | } 176 | 177 | int fd_success = open("_tests_ok", O_APPEND | O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); 178 | int fd_bad = open("_tests_fail", O_APPEND | O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); 179 | 180 | DBGT("running tests...\n"); 181 | int ok = 0; 182 | int failed = 0; 183 | int stopped = 0; 184 | test *cur_t = test_main.tests; 185 | int i = 1; 186 | while (cur_t) { 187 | cur_t->setup(cur_t); 188 | test *next_test = cur_t->_next; 189 | DBGT("TEST %i/%i : running test %s\n", i, test_main.test_count, cur_t->name); 190 | i++; 191 | int start_error_count = get_error_count(); 192 | int res = cur_t->f(cur_t); 193 | if (res == TEST_RES_OK && get_error_count() != start_error_count) { 194 | res = TEST_RES_FAIL; 195 | } 196 | cur_t->test_result = res; 197 | int fd = res == TEST_RES_OK ? fd_success : fd_bad; 198 | write(fd, cur_t->name, strlen(cur_t->name)); 199 | write(fd, "\n", 1); 200 | switch (res) { 201 | case TEST_RES_OK: 202 | ok++; 203 | printf(" .. ok\n"); 204 | break; 205 | case TEST_RES_FAIL: 206 | failed++; 207 | printf(" .. FAILED\n"); 208 | if (test_main.on_stop) test_main.on_stop(cur_t); 209 | add_res(cur_t, &test_main.failed, &test_main.failed_last); 210 | break; 211 | case TEST_RES_ASSERT: 212 | stopped++; 213 | printf(" .. ABORTED\n"); 214 | if (test_main.on_stop) test_main.on_stop(cur_t); 215 | add_res(cur_t, &test_main.stopped, &test_main.stopped_last); 216 | break; 217 | } 218 | cur_t->teardown(cur_t); 219 | free(cur_t); 220 | cur_t = next_test; 221 | } 222 | close(fd_success); 223 | close(fd_bad); 224 | DBGT("ran %i tests\n", test_main.test_count); 225 | printf("Test report, %i tests\n", test_main.test_count); 226 | printf("%i succeeded\n", ok); 227 | printf("%i failed\n", failed); 228 | dump_res(&test_main.failed); 229 | printf("%i stopped\n", stopped); 230 | dump_res(&test_main.stopped); 231 | if (ok < test_main.test_count) { 232 | printf("\nFAILED\n"); 233 | return -1; 234 | } else { 235 | printf("\nALL TESTS OK\n"); 236 | return 0; 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/src/test/testrunner.h: -------------------------------------------------------------------------------- 1 | /* 2 | * testrunner.h 3 | * 4 | * Created on: Jun 19, 2013 5 | * Author: petera 6 | */ 7 | 8 | /* 9 | 10 | file mysuite.c: 11 | 12 | SUITE(mysuite) 13 | 14 | static void setup(test *t) {} 15 | 16 | static void teardown(test *t) {} 17 | 18 | TEST(mytest) { 19 | printf("mytest runs now..\n"); 20 | return 0; 21 | } TEST_END 22 | 23 | SUITE_TESTS(mysuite) 24 | ADD_TEST(mytest) 25 | SUITE_END(mysuite) 26 | 27 | 28 | 29 | file mysuite2.c: 30 | 31 | SUITE(mysuite2) 32 | 33 | static void setup(test *t) {} 34 | 35 | static void teardown(test *t) {} 36 | 37 | TEST(mytest2a) { 38 | printf("mytest2a runs now..\n"); 39 | return 0; 40 | } TEST_END 41 | 42 | TEST(mytest2b) { 43 | printf("mytest2b runs now..\n"); 44 | return 0; 45 | } TEST_END 46 | 47 | SUITE_TESTS(mysuite2) 48 | ADD_TEST(mytest2a) 49 | ADD_TEST(mytest2b) 50 | SUITE_END(mysuite2) 51 | 52 | 53 | some other file.c: 54 | 55 | void add_suites() { 56 | ADD_SUITE(mysuite); 57 | ADD_SUITE(mysuite2); 58 | } 59 | */ 60 | 61 | #ifndef TESTRUNNER_H_ 62 | #define TESTRUNNER_H_ 63 | 64 | #define TEST_RES_OK 0 65 | #define TEST_RES_FAIL -1 66 | #define TEST_RES_ASSERT -2 67 | 68 | #define ERREXIT() if (get_abort_on_error()) abort(); else inc_error_count() 69 | 70 | struct test_s; 71 | 72 | typedef int (*test_f)(struct test_s *t); 73 | 74 | typedef struct test_s { 75 | test_f f; 76 | char name[256]; 77 | void *data; 78 | void (*setup)(struct test_s *t); 79 | void (*teardown)(struct test_s *t); 80 | struct test_s *_next; 81 | unsigned char test_result; 82 | } test; 83 | 84 | typedef struct test_res_s { 85 | char name[256]; 86 | struct test_res_s *_next; 87 | } test_res; 88 | 89 | #define TEST_CHECK(x) if (!(x)) { \ 90 | printf(" TEST FAIL %s:%d\n", __FILE__, __LINE__); \ 91 | goto __fail_stop; \ 92 | } 93 | #define TEST_CHECK_EQ(x, y) if ((x) != (y)) { \ 94 | printf(" TEST FAIL %s:%d, %d != %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ 95 | goto __fail_stop; \ 96 | } 97 | #define TEST_CHECK_NEQ(x, y) if ((x) == (y)) { \ 98 | printf(" TEST FAIL %s:%d, %d == %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ 99 | goto __fail_stop; \ 100 | } 101 | #define TEST_CHECK_GT(x, y) if ((x) <= (y)) { \ 102 | printf(" TEST FAIL %s:%d, %d <= %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ 103 | goto __fail_stop; \ 104 | } 105 | #define TEST_CHECK_LT(x, y) if ((x) >= (y)) { \ 106 | printf(" TEST FAIL %s:%d, %d >= %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ 107 | goto __fail_stop; \ 108 | } 109 | #define TEST_CHECK_GE(x, y) if ((x) < (y)) { \ 110 | printf(" TEST FAIL %s:%d, %d < %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ 111 | goto __fail_stop; \ 112 | } 113 | #define TEST_CHECK_LE(x, y) if ((x) > (y)) { \ 114 | printf(" TEST FAIL %s:%d, %d > %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ 115 | goto __fail_stop; \ 116 | } 117 | #define TEST_ASSERT(x) if (!(x)) { \ 118 | printf(" TEST ASSERT %s:%d\n", __FILE__, __LINE__); \ 119 | goto __fail_assert; \ 120 | } 121 | 122 | #define DBGT(...) printf(__VA_ARGS__) 123 | 124 | #define str(s) #s 125 | 126 | #define SUITE(sui) 127 | 128 | #define SUITE_TESTS(sui) \ 129 | void _add_suite_tests_##sui(void) { 130 | 131 | #define SUITE_END(sui) \ 132 | } 133 | 134 | #define ADD_TEST(tf) \ 135 | _add_test(__test_##tf, str(tf), setup, teardown, 0); 136 | 137 | #define ADD_TEST_NON_DEFAULT(tf) \ 138 | _add_test(__test_##tf, str(tf), setup, teardown, 1); 139 | 140 | #define ADD_SUITE(sui) \ 141 | extern void _add_suite_tests_##sui(void); \ 142 | _add_suite_tests_##sui(); 143 | 144 | #define TEST(tf) \ 145 | static int __test_##tf(struct test_s *t) { do 146 | 147 | #define TEST_END \ 148 | while(0); \ 149 | __fail_stop: return TEST_RES_FAIL; \ 150 | __fail_assert: return TEST_RES_ASSERT; \ 151 | } 152 | 153 | int set_abort_on_error(int val); 154 | int get_abort_on_error(void); 155 | int get_error_count(void); 156 | void inc_error_count(void); 157 | 158 | void add_suites(void); 159 | void test_init(void (*on_stop)(test *t)); 160 | // returns 0 if all tests ok, -1 if any test failed, -2 on badness 161 | int run_tests(int argc, char **args); 162 | void _add_suite(const char *suite_name); 163 | void _add_test(test_f f, char *name, void (*setup)(test *t), void (*teardown)(test *t), int non_default); 164 | 165 | #endif /* TESTRUNNER_H_ */ 166 | -------------------------------------------------------------------------------- /components/mkspiffs/spiffs/src/test/testsuites.c: -------------------------------------------------------------------------------- 1 | /* 2 | * testsuites.c 3 | * 4 | * Created on: Jun 19, 2013 5 | * Author: petera 6 | */ 7 | 8 | #include "testrunner.h" 9 | 10 | void add_suites(void) { 11 | //ADD_SUITE(dev_tests); 12 | ADD_SUITE(check_tests); 13 | ADD_SUITE(hydrogen_tests); 14 | ADD_SUITE(bug_tests); 15 | } 16 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/ArgException.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ArgException.h 6 | * 7 | * Copyright (c) 2003, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_ARG_EXCEPTION_H 25 | #define TCLAP_ARG_EXCEPTION_H 26 | 27 | #include 28 | #include 29 | 30 | namespace TCLAP { 31 | 32 | /** 33 | * A simple class that defines and argument exception. Should be caught 34 | * whenever a CmdLine is created and parsed. 35 | */ 36 | class ArgException : public std::exception 37 | { 38 | public: 39 | 40 | /** 41 | * Constructor. 42 | * \param text - The text of the exception. 43 | * \param id - The text identifying the argument source. 44 | * \param td - Text describing the type of ArgException it is. 45 | * of the exception. 46 | */ 47 | ArgException( const std::string& text = "undefined exception", 48 | const std::string& id = "undefined", 49 | const std::string& td = "Generic ArgException") 50 | : std::exception(), 51 | _errorText(text), 52 | _argId( id ), 53 | _typeDescription(td) 54 | { } 55 | 56 | /** 57 | * Destructor. 58 | */ 59 | virtual ~ArgException() throw() { } 60 | 61 | /** 62 | * Returns the error text. 63 | */ 64 | std::string error() const { return ( _errorText ); } 65 | 66 | /** 67 | * Returns the argument id. 68 | */ 69 | std::string argId() const 70 | { 71 | if ( _argId == "undefined" ) 72 | return " "; 73 | else 74 | return ( "Argument: " + _argId ); 75 | } 76 | 77 | /** 78 | * Returns the arg id and error text. 79 | */ 80 | const char* what() const throw() 81 | { 82 | static std::string ex; 83 | ex = _argId + " -- " + _errorText; 84 | return ex.c_str(); 85 | } 86 | 87 | /** 88 | * Returns the type of the exception. Used to explain and distinguish 89 | * between different child exceptions. 90 | */ 91 | std::string typeDescription() const 92 | { 93 | return _typeDescription; 94 | } 95 | 96 | 97 | private: 98 | 99 | /** 100 | * The text of the exception message. 101 | */ 102 | std::string _errorText; 103 | 104 | /** 105 | * The argument related to this exception. 106 | */ 107 | std::string _argId; 108 | 109 | /** 110 | * Describes the type of the exception. Used to distinguish 111 | * between different child exceptions. 112 | */ 113 | std::string _typeDescription; 114 | 115 | }; 116 | 117 | /** 118 | * Thrown from within the child Arg classes when it fails to properly 119 | * parse the argument it has been passed. 120 | */ 121 | class ArgParseException : public ArgException 122 | { 123 | public: 124 | /** 125 | * Constructor. 126 | * \param text - The text of the exception. 127 | * \param id - The text identifying the argument source 128 | * of the exception. 129 | */ 130 | ArgParseException( const std::string& text = "undefined exception", 131 | const std::string& id = "undefined" ) 132 | : ArgException( text, 133 | id, 134 | std::string( "Exception found while parsing " ) + 135 | std::string( "the value the Arg has been passed." )) 136 | { } 137 | }; 138 | 139 | /** 140 | * Thrown from CmdLine when the arguments on the command line are not 141 | * properly specified, e.g. too many arguments, required argument missing, etc. 142 | */ 143 | class CmdLineParseException : public ArgException 144 | { 145 | public: 146 | /** 147 | * Constructor. 148 | * \param text - The text of the exception. 149 | * \param id - The text identifying the argument source 150 | * of the exception. 151 | */ 152 | CmdLineParseException( const std::string& text = "undefined exception", 153 | const std::string& id = "undefined" ) 154 | : ArgException( text, 155 | id, 156 | std::string( "Exception found when the values ") + 157 | std::string( "on the command line do not meet ") + 158 | std::string( "the requirements of the defined ") + 159 | std::string( "Args." )) 160 | { } 161 | }; 162 | 163 | /** 164 | * Thrown from Arg and CmdLine when an Arg is improperly specified, e.g. 165 | * same flag as another Arg, same name, etc. 166 | */ 167 | class SpecificationException : public ArgException 168 | { 169 | public: 170 | /** 171 | * Constructor. 172 | * \param text - The text of the exception. 173 | * \param id - The text identifying the argument source 174 | * of the exception. 175 | */ 176 | SpecificationException( const std::string& text = "undefined exception", 177 | const std::string& id = "undefined" ) 178 | : ArgException( text, 179 | id, 180 | std::string("Exception found when an Arg object ")+ 181 | std::string("is improperly defined by the ") + 182 | std::string("developer." )) 183 | { } 184 | 185 | }; 186 | 187 | class ExitException { 188 | public: 189 | ExitException(int estat) : _estat(estat) {} 190 | 191 | int getExitStatus() const { return _estat; } 192 | 193 | private: 194 | int _estat; 195 | }; 196 | 197 | } // namespace TCLAP 198 | 199 | #endif 200 | 201 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/ArgTraits.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ArgTraits.h 6 | * 7 | * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | // This is an internal tclap file, you should probably not have to 24 | // include this directly 25 | 26 | #ifndef TCLAP_ARGTRAITS_H 27 | #define TCLAP_ARGTRAITS_H 28 | 29 | namespace TCLAP { 30 | 31 | // We use two empty structs to get compile type specialization 32 | // function to work 33 | 34 | /** 35 | * A value like argument value type is a value that can be set using 36 | * operator>>. This is the default value type. 37 | */ 38 | struct ValueLike { 39 | typedef ValueLike ValueCategory; 40 | virtual ~ValueLike() {} 41 | }; 42 | 43 | /** 44 | * A string like argument value type is a value that can be set using 45 | * operator=(string). Usefull if the value type contains spaces which 46 | * will be broken up into individual tokens by operator>>. 47 | */ 48 | struct StringLike { 49 | virtual ~StringLike() {} 50 | }; 51 | 52 | /** 53 | * A class can inherit from this object to make it have string like 54 | * traits. This is a compile time thing and does not add any overhead 55 | * to the inherenting class. 56 | */ 57 | struct StringLikeTrait { 58 | typedef StringLike ValueCategory; 59 | virtual ~StringLikeTrait() {} 60 | }; 61 | 62 | /** 63 | * A class can inherit from this object to make it have value like 64 | * traits. This is a compile time thing and does not add any overhead 65 | * to the inherenting class. 66 | */ 67 | struct ValueLikeTrait { 68 | typedef ValueLike ValueCategory; 69 | virtual ~ValueLikeTrait() {} 70 | }; 71 | 72 | /** 73 | * Arg traits are used to get compile type specialization when parsing 74 | * argument values. Using an ArgTraits you can specify the way that 75 | * values gets assigned to any particular type during parsing. The two 76 | * supported types are StringLike and ValueLike. 77 | */ 78 | template 79 | struct ArgTraits { 80 | typedef typename T::ValueCategory ValueCategory; 81 | virtual ~ArgTraits() {} 82 | //typedef ValueLike ValueCategory; 83 | }; 84 | 85 | #endif 86 | 87 | } // namespace 88 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/COPYING: -------------------------------------------------------------------------------- 1 | 2 | 3 | Copyright (c) 2003 Michael E. Smoot 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without restriction, 8 | including without limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of the Software, 10 | and to permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | 25 | 26 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/CmdLineInterface.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: CmdLineInterface.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_COMMANDLINE_INTERFACE_H 24 | #define TCLAP_COMMANDLINE_INTERFACE_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | 33 | namespace TCLAP { 34 | 35 | class Arg; 36 | class CmdLineOutput; 37 | class XorHandler; 38 | 39 | /** 40 | * The base class that manages the command line definition and passes 41 | * along the parsing to the appropriate Arg classes. 42 | */ 43 | class CmdLineInterface 44 | { 45 | public: 46 | 47 | /** 48 | * Destructor 49 | */ 50 | virtual ~CmdLineInterface() {} 51 | 52 | /** 53 | * Adds an argument to the list of arguments to be parsed. 54 | * \param a - Argument to be added. 55 | */ 56 | virtual void add( Arg& a )=0; 57 | 58 | /** 59 | * An alternative add. Functionally identical. 60 | * \param a - Argument to be added. 61 | */ 62 | virtual void add( Arg* a )=0; 63 | 64 | /** 65 | * Add two Args that will be xor'd. 66 | * If this method is used, add does 67 | * not need to be called. 68 | * \param a - Argument to be added and xor'd. 69 | * \param b - Argument to be added and xor'd. 70 | */ 71 | virtual void xorAdd( Arg& a, Arg& b )=0; 72 | 73 | /** 74 | * Add a list of Args that will be xor'd. If this method is used, 75 | * add does not need to be called. 76 | * \param xors - List of Args to be added and xor'd. 77 | */ 78 | virtual void xorAdd( std::vector& xors )=0; 79 | 80 | /** 81 | * Parses the command line. 82 | * \param argc - Number of arguments. 83 | * \param argv - Array of arguments. 84 | */ 85 | virtual void parse(int argc, const char * const * argv)=0; 86 | 87 | /** 88 | * Parses the command line. 89 | * \param args - A vector of strings representing the args. 90 | * args[0] is still the program name. 91 | */ 92 | void parse(std::vector& args); 93 | 94 | /** 95 | * Returns the CmdLineOutput object. 96 | */ 97 | virtual CmdLineOutput* getOutput()=0; 98 | 99 | /** 100 | * \param co - CmdLineOutput object that we want to use instead. 101 | */ 102 | virtual void setOutput(CmdLineOutput* co)=0; 103 | 104 | /** 105 | * Returns the version string. 106 | */ 107 | virtual std::string& getVersion()=0; 108 | 109 | /** 110 | * Returns the program name string. 111 | */ 112 | virtual std::string& getProgramName()=0; 113 | 114 | /** 115 | * Returns the argList. 116 | */ 117 | virtual std::list& getArgList()=0; 118 | 119 | /** 120 | * Returns the XorHandler. 121 | */ 122 | virtual XorHandler& getXorHandler()=0; 123 | 124 | /** 125 | * Returns the delimiter string. 126 | */ 127 | virtual char getDelimiter()=0; 128 | 129 | /** 130 | * Returns the message string. 131 | */ 132 | virtual std::string& getMessage()=0; 133 | 134 | /** 135 | * Indicates whether or not the help and version switches were created 136 | * automatically. 137 | */ 138 | virtual bool hasHelpAndVersion()=0; 139 | 140 | /** 141 | * Resets the instance as if it had just been constructed so that the 142 | * instance can be reused. 143 | */ 144 | virtual void reset()=0; 145 | }; 146 | 147 | } //namespace 148 | 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/CmdLineOutput.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | /****************************************************************************** 4 | * 5 | * file: CmdLineOutput.h 6 | * 7 | * Copyright (c) 2004, Michael E. Smoot 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_CMDLINEOUTPUT_H 24 | #define TCLAP_CMDLINEOUTPUT_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | namespace TCLAP { 34 | 35 | class CmdLineInterface; 36 | class ArgException; 37 | 38 | /** 39 | * The interface that any output object must implement. 40 | */ 41 | class CmdLineOutput 42 | { 43 | 44 | public: 45 | 46 | /** 47 | * Virtual destructor. 48 | */ 49 | virtual ~CmdLineOutput() {} 50 | 51 | /** 52 | * Generates some sort of output for the USAGE. 53 | * \param c - The CmdLine object the output is generated for. 54 | */ 55 | virtual void usage(CmdLineInterface& c)=0; 56 | 57 | /** 58 | * Generates some sort of output for the version. 59 | * \param c - The CmdLine object the output is generated for. 60 | */ 61 | virtual void version(CmdLineInterface& c)=0; 62 | 63 | /** 64 | * Generates some sort of output for a failure. 65 | * \param c - The CmdLine object the output is generated for. 66 | * \param e - The ArgException that caused the failure. 67 | */ 68 | virtual void failure( CmdLineInterface& c, 69 | ArgException& e )=0; 70 | 71 | }; 72 | 73 | } //namespace TCLAP 74 | #endif 75 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/Constraint.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: Constraint.h 5 | * 6 | * Copyright (c) 2005, Michael E. Smoot 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | #ifndef TCLAP_CONSTRAINT_H 23 | #define TCLAP_CONSTRAINT_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace TCLAP { 33 | 34 | /** 35 | * The interface that defines the interaction between the Arg and Constraint. 36 | */ 37 | template 38 | class Constraint 39 | { 40 | 41 | public: 42 | /** 43 | * Returns a description of the Constraint. 44 | */ 45 | virtual std::string description() const =0; 46 | 47 | /** 48 | * Returns the short ID for the Constraint. 49 | */ 50 | virtual std::string shortID() const =0; 51 | 52 | /** 53 | * The method used to verify that the value parsed from the command 54 | * line meets the constraint. 55 | * \param value - The value that will be checked. 56 | */ 57 | virtual bool check(const T& value) const =0; 58 | 59 | /** 60 | * Destructor. 61 | * Silences warnings about Constraint being a base class with virtual 62 | * functions but without a virtual destructor. 63 | */ 64 | virtual ~Constraint() { ; } 65 | }; 66 | 67 | } //namespace TCLAP 68 | #endif 69 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/DocBookOutput.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: DocBookOutput.h 6 | * 7 | * Copyright (c) 2004, Michael E. Smoot 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_DOCBOOKOUTPUT_H 24 | #define TCLAP_DOCBOOKOUTPUT_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace TCLAP { 38 | 39 | /** 40 | * A class that generates DocBook output for usage() method for the 41 | * given CmdLine and its Args. 42 | */ 43 | class DocBookOutput : public CmdLineOutput 44 | { 45 | 46 | public: 47 | 48 | /** 49 | * Prints the usage to stdout. Can be overridden to 50 | * produce alternative behavior. 51 | * \param c - The CmdLine object the output is generated for. 52 | */ 53 | virtual void usage(CmdLineInterface& c); 54 | 55 | /** 56 | * Prints the version to stdout. Can be overridden 57 | * to produce alternative behavior. 58 | * \param c - The CmdLine object the output is generated for. 59 | */ 60 | virtual void version(CmdLineInterface& c); 61 | 62 | /** 63 | * Prints (to stderr) an error message, short usage 64 | * Can be overridden to produce alternative behavior. 65 | * \param c - The CmdLine object the output is generated for. 66 | * \param e - The ArgException that caused the failure. 67 | */ 68 | virtual void failure(CmdLineInterface& c, 69 | ArgException& e ); 70 | 71 | protected: 72 | 73 | /** 74 | * Substitutes the char r for string x in string s. 75 | * \param s - The string to operate on. 76 | * \param r - The char to replace. 77 | * \param x - What to replace r with. 78 | */ 79 | void substituteSpecialChars( std::string& s, char r, std::string& x ); 80 | void removeChar( std::string& s, char r); 81 | void basename( std::string& s ); 82 | 83 | void printShortArg(Arg* it); 84 | void printLongArg(Arg* it); 85 | 86 | char theDelimiter; 87 | }; 88 | 89 | 90 | inline void DocBookOutput::version(CmdLineInterface& _cmd) 91 | { 92 | std::cout << _cmd.getVersion() << std::endl; 93 | } 94 | 95 | inline void DocBookOutput::usage(CmdLineInterface& _cmd ) 96 | { 97 | std::list argList = _cmd.getArgList(); 98 | std::string progName = _cmd.getProgramName(); 99 | std::string xversion = _cmd.getVersion(); 100 | theDelimiter = _cmd.getDelimiter(); 101 | XorHandler xorHandler = _cmd.getXorHandler(); 102 | std::vector< std::vector > xorList = xorHandler.getXorList(); 103 | basename(progName); 104 | 105 | std::cout << "" << std::endl; 106 | std::cout << "" << std::endl << std::endl; 108 | 109 | std::cout << "" << std::endl; 110 | 111 | std::cout << "" << std::endl; 112 | std::cout << "" << progName << "" << std::endl; 113 | std::cout << "1" << std::endl; 114 | std::cout << "" << std::endl; 115 | 116 | std::cout << "" << std::endl; 117 | std::cout << "" << progName << "" << std::endl; 118 | std::cout << "" << _cmd.getMessage() << "" << std::endl; 119 | std::cout << "" << std::endl; 120 | 121 | std::cout << "" << std::endl; 122 | std::cout << "" << std::endl; 123 | 124 | std::cout << "" << progName << "" << std::endl; 125 | 126 | // xor 127 | for ( int i = 0; (unsigned int)i < xorList.size(); i++ ) 128 | { 129 | std::cout << "" << std::endl; 130 | for ( ArgVectorIterator it = xorList[i].begin(); 131 | it != xorList[i].end(); it++ ) 132 | printShortArg((*it)); 133 | 134 | std::cout << "" << std::endl; 135 | } 136 | 137 | // rest of args 138 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 139 | if ( !xorHandler.contains( (*it) ) ) 140 | printShortArg((*it)); 141 | 142 | std::cout << "" << std::endl; 143 | std::cout << "" << std::endl; 144 | 145 | std::cout << "" << std::endl; 146 | std::cout << "Description" << std::endl; 147 | std::cout << "" << std::endl; 148 | std::cout << _cmd.getMessage() << std::endl; 149 | std::cout << "" << std::endl; 150 | std::cout << "" << std::endl; 151 | 152 | std::cout << "" << std::endl; 153 | std::cout << "Options" << std::endl; 154 | 155 | std::cout << "" << std::endl; 156 | 157 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 158 | printLongArg((*it)); 159 | 160 | std::cout << "" << std::endl; 161 | std::cout << "" << std::endl; 162 | 163 | std::cout << "" << std::endl; 164 | std::cout << "Version" << std::endl; 165 | std::cout << "" << std::endl; 166 | std::cout << xversion << std::endl; 167 | std::cout << "" << std::endl; 168 | std::cout << "" << std::endl; 169 | 170 | std::cout << "" << std::endl; 171 | 172 | } 173 | 174 | inline void DocBookOutput::failure( CmdLineInterface& _cmd, 175 | ArgException& e ) 176 | { 177 | static_cast(_cmd); // unused 178 | std::cout << e.what() << std::endl; 179 | throw ExitException(1); 180 | } 181 | 182 | inline void DocBookOutput::substituteSpecialChars( std::string& s, 183 | char r, 184 | std::string& x ) 185 | { 186 | size_t p; 187 | while ( (p = s.find_first_of(r)) != std::string::npos ) 188 | { 189 | s.erase(p,1); 190 | s.insert(p,x); 191 | } 192 | } 193 | 194 | inline void DocBookOutput::removeChar( std::string& s, char r) 195 | { 196 | size_t p; 197 | while ( (p = s.find_first_of(r)) != std::string::npos ) 198 | { 199 | s.erase(p,1); 200 | } 201 | } 202 | 203 | inline void DocBookOutput::basename( std::string& s ) 204 | { 205 | size_t p = s.find_last_of('/'); 206 | if ( p != std::string::npos ) 207 | { 208 | s.erase(0, p + 1); 209 | } 210 | } 211 | 212 | inline void DocBookOutput::printShortArg(Arg* a) 213 | { 214 | std::string lt = "<"; 215 | std::string gt = ">"; 216 | 217 | std::string id = a->shortID(); 218 | substituteSpecialChars(id,'<',lt); 219 | substituteSpecialChars(id,'>',gt); 220 | removeChar(id,'['); 221 | removeChar(id,']'); 222 | 223 | std::string choice = "opt"; 224 | if ( a->isRequired() ) 225 | choice = "plain"; 226 | 227 | std::cout << "acceptsMultipleValues() ) 229 | std::cout << " rep='repeat'"; 230 | 231 | 232 | std::cout << '>'; 233 | if ( !a->getFlag().empty() ) 234 | std::cout << a->flagStartChar() << a->getFlag(); 235 | else 236 | std::cout << a->nameStartString() << a->getName(); 237 | if ( a->isValueRequired() ) 238 | { 239 | std::string arg = a->shortID(); 240 | removeChar(arg,'['); 241 | removeChar(arg,']'); 242 | removeChar(arg,'<'); 243 | removeChar(arg,'>'); 244 | arg.erase(0, arg.find_last_of(theDelimiter) + 1); 245 | std::cout << theDelimiter; 246 | std::cout << "" << arg << ""; 247 | } 248 | std::cout << "" << std::endl; 249 | 250 | } 251 | 252 | inline void DocBookOutput::printLongArg(Arg* a) 253 | { 254 | std::string lt = "<"; 255 | std::string gt = ">"; 256 | 257 | std::string desc = a->getDescription(); 258 | substituteSpecialChars(desc,'<',lt); 259 | substituteSpecialChars(desc,'>',gt); 260 | 261 | std::cout << "" << std::endl; 262 | 263 | if ( !a->getFlag().empty() ) 264 | { 265 | std::cout << "" << std::endl; 266 | std::cout << "" << std::endl; 269 | std::cout << "" << std::endl; 270 | } 271 | 272 | std::cout << "" << std::endl; 273 | std::cout << "" << std::endl; 287 | std::cout << "" << std::endl; 288 | 289 | std::cout << "" << std::endl; 290 | std::cout << "" << std::endl; 291 | std::cout << desc << std::endl; 292 | std::cout << "" << std::endl; 293 | std::cout << "" << std::endl; 294 | 295 | std::cout << "" << std::endl; 296 | } 297 | 298 | } //namespace TCLAP 299 | #endif 300 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/HelpVisitor.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: HelpVisitor.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | #ifndef TCLAP_HELP_VISITOR_H 23 | #define TCLAP_HELP_VISITOR_H 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | namespace TCLAP { 30 | 31 | /** 32 | * A Visitor object that calls the usage method of the given CmdLineOutput 33 | * object for the specified CmdLine object. 34 | */ 35 | class HelpVisitor: public Visitor 36 | { 37 | private: 38 | /** 39 | * Prevent accidental copying. 40 | */ 41 | HelpVisitor(const HelpVisitor& rhs); 42 | HelpVisitor& operator=(const HelpVisitor& rhs); 43 | 44 | protected: 45 | 46 | /** 47 | * The CmdLine the output will be generated for. 48 | */ 49 | CmdLineInterface* _cmd; 50 | 51 | /** 52 | * The output object. 53 | */ 54 | CmdLineOutput** _out; 55 | 56 | public: 57 | 58 | /** 59 | * Constructor. 60 | * \param cmd - The CmdLine the output will be generated for. 61 | * \param out - The type of output. 62 | */ 63 | HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out) 64 | : Visitor(), _cmd( cmd ), _out( out ) { } 65 | 66 | /** 67 | * Calls the usage method of the CmdLineOutput for the 68 | * specified CmdLine. 69 | */ 70 | void visit() { (*_out)->usage(*_cmd); throw ExitException(0); } 71 | 72 | }; 73 | 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/IgnoreRestVisitor.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: IgnoreRestVisitor.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | 23 | #ifndef TCLAP_IGNORE_REST_VISITOR_H 24 | #define TCLAP_IGNORE_REST_VISITOR_H 25 | 26 | #include 27 | #include 28 | 29 | namespace TCLAP { 30 | 31 | /** 32 | * A Vistor that tells the CmdLine to begin ignoring arguments after 33 | * this one is parsed. 34 | */ 35 | class IgnoreRestVisitor: public Visitor 36 | { 37 | public: 38 | 39 | /** 40 | * Constructor. 41 | */ 42 | IgnoreRestVisitor() : Visitor() {} 43 | 44 | /** 45 | * Sets Arg::_ignoreRest. 46 | */ 47 | void visit() { Arg::beginIgnoring(); } 48 | }; 49 | 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/MultiSwitchArg.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: MultiSwitchArg.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * Copyright (c) 2005, Michael E. Smoot, Daniel Aarno, Erik Zeek. 9 | * All rights reverved. 10 | * 11 | * See the file COPYING in the top directory of this distribution for 12 | * more information. 13 | * 14 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | *****************************************************************************/ 23 | 24 | 25 | #ifndef TCLAP_MULTI_SWITCH_ARG_H 26 | #define TCLAP_MULTI_SWITCH_ARG_H 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | namespace TCLAP { 34 | 35 | /** 36 | * A multiple switch argument. If the switch is set on the command line, then 37 | * the getValue method will return the number of times the switch appears. 38 | */ 39 | class MultiSwitchArg : public SwitchArg 40 | { 41 | protected: 42 | 43 | /** 44 | * The value of the switch. 45 | */ 46 | int _value; 47 | 48 | /** 49 | * Used to support the reset() method so that ValueArg can be 50 | * reset to their constructed value. 51 | */ 52 | int _default; 53 | 54 | public: 55 | 56 | /** 57 | * MultiSwitchArg constructor. 58 | * \param flag - The one character flag that identifies this 59 | * argument on the command line. 60 | * \param name - A one word name for the argument. Can be 61 | * used as a long flag on the command line. 62 | * \param desc - A description of what the argument is for or 63 | * does. 64 | * \param init - Optional. The initial/default value of this Arg. 65 | * Defaults to 0. 66 | * \param v - An optional visitor. You probably should not 67 | * use this unless you have a very good reason. 68 | */ 69 | MultiSwitchArg(const std::string& flag, 70 | const std::string& name, 71 | const std::string& desc, 72 | int init = 0, 73 | Visitor* v = NULL); 74 | 75 | 76 | /** 77 | * MultiSwitchArg constructor. 78 | * \param flag - The one character flag that identifies this 79 | * argument on the command line. 80 | * \param name - A one word name for the argument. Can be 81 | * used as a long flag on the command line. 82 | * \param desc - A description of what the argument is for or 83 | * does. 84 | * \param parser - A CmdLine parser object to add this Arg to 85 | * \param init - Optional. The initial/default value of this Arg. 86 | * Defaults to 0. 87 | * \param v - An optional visitor. You probably should not 88 | * use this unless you have a very good reason. 89 | */ 90 | MultiSwitchArg(const std::string& flag, 91 | const std::string& name, 92 | const std::string& desc, 93 | CmdLineInterface& parser, 94 | int init = 0, 95 | Visitor* v = NULL); 96 | 97 | 98 | /** 99 | * Handles the processing of the argument. 100 | * This re-implements the SwitchArg version of this method to set the 101 | * _value of the argument appropriately. 102 | * \param i - Pointer the the current argument in the list. 103 | * \param args - Mutable list of strings. Passed 104 | * in from main(). 105 | */ 106 | virtual bool processArg(int* i, std::vector& args); 107 | 108 | /** 109 | * Returns int, the number of times the switch has been set. 110 | */ 111 | int getValue(); 112 | 113 | /** 114 | * Returns the shortID for this Arg. 115 | */ 116 | std::string shortID(const std::string& val) const; 117 | 118 | /** 119 | * Returns the longID for this Arg. 120 | */ 121 | std::string longID(const std::string& val) const; 122 | 123 | void reset(); 124 | 125 | }; 126 | 127 | ////////////////////////////////////////////////////////////////////// 128 | //BEGIN MultiSwitchArg.cpp 129 | ////////////////////////////////////////////////////////////////////// 130 | inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, 131 | const std::string& name, 132 | const std::string& desc, 133 | int init, 134 | Visitor* v ) 135 | : SwitchArg(flag, name, desc, false, v), 136 | _value( init ), 137 | _default( init ) 138 | { } 139 | 140 | inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, 141 | const std::string& name, 142 | const std::string& desc, 143 | CmdLineInterface& parser, 144 | int init, 145 | Visitor* v ) 146 | : SwitchArg(flag, name, desc, false, v), 147 | _value( init ), 148 | _default( init ) 149 | { 150 | parser.add( this ); 151 | } 152 | 153 | inline int MultiSwitchArg::getValue() { return _value; } 154 | 155 | inline bool MultiSwitchArg::processArg(int *i, std::vector& args) 156 | { 157 | if ( _ignoreable && Arg::ignoreRest() ) 158 | return false; 159 | 160 | if ( argMatches( args[*i] )) 161 | { 162 | // so the isSet() method will work 163 | _alreadySet = true; 164 | 165 | // Matched argument: increment value. 166 | ++_value; 167 | 168 | _checkWithVisitor(); 169 | 170 | return true; 171 | } 172 | else if ( combinedSwitchesMatch( args[*i] ) ) 173 | { 174 | // so the isSet() method will work 175 | _alreadySet = true; 176 | 177 | // Matched argument: increment value. 178 | ++_value; 179 | 180 | // Check for more in argument and increment value. 181 | while ( combinedSwitchesMatch( args[*i] ) ) 182 | ++_value; 183 | 184 | _checkWithVisitor(); 185 | 186 | return false; 187 | } 188 | else 189 | return false; 190 | } 191 | 192 | inline std::string 193 | MultiSwitchArg::shortID(const std::string& val) const 194 | { 195 | return Arg::shortID(val) + " ... "; 196 | } 197 | 198 | inline std::string 199 | MultiSwitchArg::longID(const std::string& val) const 200 | { 201 | return Arg::longID(val) + " (accepted multiple times)"; 202 | } 203 | 204 | inline void 205 | MultiSwitchArg::reset() 206 | { 207 | MultiSwitchArg::_value = MultiSwitchArg::_default; 208 | } 209 | 210 | ////////////////////////////////////////////////////////////////////// 211 | //END MultiSwitchArg.cpp 212 | ////////////////////////////////////////////////////////////////////// 213 | 214 | } //namespace TCLAP 215 | 216 | #endif 217 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/OptionalUnlabeledTracker.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | /****************************************************************************** 4 | * 5 | * file: OptionalUnlabeledTracker.h 6 | * 7 | * Copyright (c) 2005, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H 25 | #define TCLAP_OPTIONAL_UNLABELED_TRACKER_H 26 | 27 | #include 28 | 29 | namespace TCLAP { 30 | 31 | class OptionalUnlabeledTracker 32 | { 33 | 34 | public: 35 | 36 | static void check( bool req, const std::string& argName ); 37 | 38 | static void gotOptional() { alreadyOptionalRef() = true; } 39 | 40 | static bool& alreadyOptional() { return alreadyOptionalRef(); } 41 | 42 | private: 43 | 44 | static bool& alreadyOptionalRef() { static bool ct = false; return ct; } 45 | }; 46 | 47 | 48 | inline void OptionalUnlabeledTracker::check( bool req, const std::string& argName ) 49 | { 50 | if ( OptionalUnlabeledTracker::alreadyOptional() ) 51 | throw( SpecificationException( 52 | "You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg", 53 | argName ) ); 54 | 55 | if ( !req ) 56 | OptionalUnlabeledTracker::gotOptional(); 57 | } 58 | 59 | 60 | } // namespace TCLAP 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/StandardTraits.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: StandardTraits.h 6 | * 7 | * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | // This is an internal tclap file, you should probably not have to 24 | // include this directly 25 | 26 | #ifndef TCLAP_STANDARD_TRAITS_H 27 | #define TCLAP_STANDARD_TRAITS_H 28 | 29 | #ifdef HAVE_CONFIG_H 30 | #include // To check for long long 31 | #endif 32 | 33 | // If Microsoft has already typedef'd wchar_t as an unsigned 34 | // short, then compiles will break because it's as if we're 35 | // creating ArgTraits twice for unsigned short. Thus... 36 | #ifdef _MSC_VER 37 | #ifndef _NATIVE_WCHAR_T_DEFINED 38 | #define TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS 39 | #endif 40 | #endif 41 | 42 | namespace TCLAP { 43 | 44 | // ====================================================================== 45 | // Integer types 46 | // ====================================================================== 47 | 48 | /** 49 | * longs have value-like semantics. 50 | */ 51 | template<> 52 | struct ArgTraits { 53 | typedef ValueLike ValueCategory; 54 | }; 55 | 56 | /** 57 | * ints have value-like semantics. 58 | */ 59 | template<> 60 | struct ArgTraits { 61 | typedef ValueLike ValueCategory; 62 | }; 63 | 64 | /** 65 | * shorts have value-like semantics. 66 | */ 67 | template<> 68 | struct ArgTraits { 69 | typedef ValueLike ValueCategory; 70 | }; 71 | 72 | /** 73 | * chars have value-like semantics. 74 | */ 75 | template<> 76 | struct ArgTraits { 77 | typedef ValueLike ValueCategory; 78 | }; 79 | 80 | #ifdef HAVE_LONG_LONG 81 | /** 82 | * long longs have value-like semantics. 83 | */ 84 | template<> 85 | struct ArgTraits { 86 | typedef ValueLike ValueCategory; 87 | }; 88 | #endif 89 | 90 | // ====================================================================== 91 | // Unsigned integer types 92 | // ====================================================================== 93 | 94 | /** 95 | * unsigned longs have value-like semantics. 96 | */ 97 | template<> 98 | struct ArgTraits { 99 | typedef ValueLike ValueCategory; 100 | }; 101 | 102 | /** 103 | * unsigned ints have value-like semantics. 104 | */ 105 | template<> 106 | struct ArgTraits { 107 | typedef ValueLike ValueCategory; 108 | }; 109 | 110 | /** 111 | * unsigned shorts have value-like semantics. 112 | */ 113 | template<> 114 | struct ArgTraits { 115 | typedef ValueLike ValueCategory; 116 | }; 117 | 118 | /** 119 | * unsigned chars have value-like semantics. 120 | */ 121 | template<> 122 | struct ArgTraits { 123 | typedef ValueLike ValueCategory; 124 | }; 125 | 126 | // Microsoft implements size_t awkwardly. 127 | #if defined(_MSC_VER) && defined(_M_X64) 128 | /** 129 | * size_ts have value-like semantics. 130 | */ 131 | template<> 132 | struct ArgTraits { 133 | typedef ValueLike ValueCategory; 134 | }; 135 | #endif 136 | 137 | 138 | #ifdef HAVE_LONG_LONG 139 | /** 140 | * unsigned long longs have value-like semantics. 141 | */ 142 | template<> 143 | struct ArgTraits { 144 | typedef ValueLike ValueCategory; 145 | }; 146 | #endif 147 | 148 | // ====================================================================== 149 | // Float types 150 | // ====================================================================== 151 | 152 | /** 153 | * floats have value-like semantics. 154 | */ 155 | template<> 156 | struct ArgTraits { 157 | typedef ValueLike ValueCategory; 158 | }; 159 | 160 | /** 161 | * doubles have value-like semantics. 162 | */ 163 | template<> 164 | struct ArgTraits { 165 | typedef ValueLike ValueCategory; 166 | }; 167 | 168 | // ====================================================================== 169 | // Other types 170 | // ====================================================================== 171 | 172 | /** 173 | * bools have value-like semantics. 174 | */ 175 | template<> 176 | struct ArgTraits { 177 | typedef ValueLike ValueCategory; 178 | }; 179 | 180 | 181 | /** 182 | * wchar_ts have value-like semantics. 183 | */ 184 | #ifndef TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS 185 | template<> 186 | struct ArgTraits { 187 | typedef ValueLike ValueCategory; 188 | }; 189 | #endif 190 | 191 | /** 192 | * Strings have string like argument traits. 193 | */ 194 | template<> 195 | struct ArgTraits { 196 | typedef StringLike ValueCategory; 197 | }; 198 | 199 | template 200 | void SetString(T &dst, const std::string &src) 201 | { 202 | dst = src; 203 | } 204 | 205 | } // namespace 206 | 207 | #endif 208 | 209 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/StdOutput.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: StdOutput.h 6 | * 7 | * Copyright (c) 2004, Michael E. Smoot 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_STDCMDLINEOUTPUT_H 24 | #define TCLAP_STDCMDLINEOUTPUT_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace TCLAP { 38 | 39 | /** 40 | * A class that isolates any output from the CmdLine object so that it 41 | * may be easily modified. 42 | */ 43 | class StdOutput : public CmdLineOutput 44 | { 45 | 46 | public: 47 | 48 | /** 49 | * Prints the usage to stdout. Can be overridden to 50 | * produce alternative behavior. 51 | * \param c - The CmdLine object the output is generated for. 52 | */ 53 | virtual void usage(CmdLineInterface& c); 54 | 55 | /** 56 | * Prints the version to stdout. Can be overridden 57 | * to produce alternative behavior. 58 | * \param c - The CmdLine object the output is generated for. 59 | */ 60 | virtual void version(CmdLineInterface& c); 61 | 62 | /** 63 | * Prints (to stderr) an error message, short usage 64 | * Can be overridden to produce alternative behavior. 65 | * \param c - The CmdLine object the output is generated for. 66 | * \param e - The ArgException that caused the failure. 67 | */ 68 | virtual void failure(CmdLineInterface& c, 69 | ArgException& e ); 70 | 71 | protected: 72 | 73 | /** 74 | * Writes a brief usage message with short args. 75 | * \param c - The CmdLine object the output is generated for. 76 | * \param os - The stream to write the message to. 77 | */ 78 | void _shortUsage( CmdLineInterface& c, std::ostream& os ) const; 79 | 80 | /** 81 | * Writes a longer usage message with long and short args, 82 | * provides descriptions and prints message. 83 | * \param c - The CmdLine object the output is generated for. 84 | * \param os - The stream to write the message to. 85 | */ 86 | void _longUsage( CmdLineInterface& c, std::ostream& os ) const; 87 | 88 | /** 89 | * This function inserts line breaks and indents long strings 90 | * according the params input. It will only break lines at spaces, 91 | * commas and pipes. 92 | * \param os - The stream to be printed to. 93 | * \param s - The string to be printed. 94 | * \param maxWidth - The maxWidth allowed for the output line. 95 | * \param indentSpaces - The number of spaces to indent the first line. 96 | * \param secondLineOffset - The number of spaces to indent the second 97 | * and all subsequent lines in addition to indentSpaces. 98 | */ 99 | void spacePrint( std::ostream& os, 100 | const std::string& s, 101 | int maxWidth, 102 | int indentSpaces, 103 | int secondLineOffset ) const; 104 | 105 | }; 106 | 107 | 108 | inline void StdOutput::version(CmdLineInterface& _cmd) 109 | { 110 | std::string progName = _cmd.getProgramName(); 111 | std::string xversion = _cmd.getVersion(); 112 | 113 | std::cout << std::endl << progName << " version: " 114 | << xversion << std::endl << std::endl; 115 | } 116 | 117 | inline void StdOutput::usage(CmdLineInterface& _cmd ) 118 | { 119 | std::cout << std::endl << "USAGE: " << std::endl << std::endl; 120 | 121 | _shortUsage( _cmd, std::cout ); 122 | 123 | std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl; 124 | 125 | _longUsage( _cmd, std::cout ); 126 | 127 | std::cout << std::endl; 128 | 129 | } 130 | 131 | inline void StdOutput::failure( CmdLineInterface& _cmd, 132 | ArgException& e ) 133 | { 134 | std::string progName = _cmd.getProgramName(); 135 | 136 | std::cerr << "PARSE ERROR: " << e.argId() << std::endl 137 | << " " << e.error() << std::endl << std::endl; 138 | 139 | if ( _cmd.hasHelpAndVersion() ) 140 | { 141 | std::cerr << "Brief USAGE: " << std::endl; 142 | 143 | _shortUsage( _cmd, std::cerr ); 144 | 145 | std::cerr << std::endl << "For complete USAGE and HELP type: " 146 | << std::endl << " " << progName << " --help" 147 | << std::endl << std::endl; 148 | } 149 | else 150 | usage(_cmd); 151 | 152 | throw ExitException(1); 153 | } 154 | 155 | inline void 156 | StdOutput::_shortUsage( CmdLineInterface& _cmd, 157 | std::ostream& os ) const 158 | { 159 | std::list argList = _cmd.getArgList(); 160 | std::string progName = _cmd.getProgramName(); 161 | XorHandler xorHandler = _cmd.getXorHandler(); 162 | std::vector< std::vector > xorList = xorHandler.getXorList(); 163 | 164 | std::string s = progName + " "; 165 | 166 | // first the xor 167 | for ( int i = 0; static_cast(i) < xorList.size(); i++ ) 168 | { 169 | s += " {"; 170 | for ( ArgVectorIterator it = xorList[i].begin(); 171 | it != xorList[i].end(); it++ ) 172 | s += (*it)->shortID() + "|"; 173 | 174 | s[s.length()-1] = '}'; 175 | } 176 | 177 | // then the rest 178 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 179 | if ( !xorHandler.contains( (*it) ) ) 180 | s += " " + (*it)->shortID(); 181 | 182 | // if the program name is too long, then adjust the second line offset 183 | int secondLineOffset = static_cast(progName.length()) + 2; 184 | if ( secondLineOffset > 75/2 ) 185 | secondLineOffset = static_cast(75/2); 186 | 187 | spacePrint( os, s, 75, 3, secondLineOffset ); 188 | } 189 | 190 | inline void 191 | StdOutput::_longUsage( CmdLineInterface& _cmd, 192 | std::ostream& os ) const 193 | { 194 | std::list argList = _cmd.getArgList(); 195 | std::string message = _cmd.getMessage(); 196 | XorHandler xorHandler = _cmd.getXorHandler(); 197 | std::vector< std::vector > xorList = xorHandler.getXorList(); 198 | 199 | // first the xor 200 | for ( int i = 0; static_cast(i) < xorList.size(); i++ ) 201 | { 202 | for ( ArgVectorIterator it = xorList[i].begin(); 203 | it != xorList[i].end(); 204 | it++ ) 205 | { 206 | spacePrint( os, (*it)->longID(), 75, 3, 3 ); 207 | spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); 208 | 209 | if ( it+1 != xorList[i].end() ) 210 | spacePrint(os, "-- OR --", 75, 9, 0); 211 | } 212 | os << std::endl << std::endl; 213 | } 214 | 215 | // then the rest 216 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 217 | if ( !xorHandler.contains( (*it) ) ) 218 | { 219 | spacePrint( os, (*it)->longID(), 75, 3, 3 ); 220 | spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); 221 | os << std::endl; 222 | } 223 | 224 | os << std::endl; 225 | 226 | spacePrint( os, message, 75, 3, 0 ); 227 | } 228 | 229 | inline void StdOutput::spacePrint( std::ostream& os, 230 | const std::string& s, 231 | int maxWidth, 232 | int indentSpaces, 233 | int secondLineOffset ) const 234 | { 235 | int len = static_cast(s.length()); 236 | 237 | if ( (len + indentSpaces > maxWidth) && maxWidth > 0 ) 238 | { 239 | int allowedLen = maxWidth - indentSpaces; 240 | int start = 0; 241 | while ( start < len ) 242 | { 243 | // find the substring length 244 | // int stringLen = std::min( len - start, allowedLen ); 245 | // doing it this way to support a VisualC++ 2005 bug 246 | using namespace std; 247 | int stringLen = min( len - start, allowedLen ); 248 | 249 | // trim the length so it doesn't end in middle of a word 250 | if ( stringLen == allowedLen ) 251 | while ( stringLen >= 0 && 252 | s[stringLen+start] != ' ' && 253 | s[stringLen+start] != ',' && 254 | s[stringLen+start] != '|' ) 255 | stringLen--; 256 | 257 | // ok, the word is longer than the line, so just split 258 | // wherever the line ends 259 | if ( stringLen <= 0 ) 260 | stringLen = allowedLen; 261 | 262 | // check for newlines 263 | for ( int i = 0; i < stringLen; i++ ) 264 | if ( s[start+i] == '\n' ) 265 | stringLen = i+1; 266 | 267 | // print the indent 268 | for ( int i = 0; i < indentSpaces; i++ ) 269 | os << " "; 270 | 271 | if ( start == 0 ) 272 | { 273 | // handle second line offsets 274 | indentSpaces += secondLineOffset; 275 | 276 | // adjust allowed len 277 | allowedLen -= secondLineOffset; 278 | } 279 | 280 | os << s.substr(start,stringLen) << std::endl; 281 | 282 | // so we don't start a line with a space 283 | while ( s[stringLen+start] == ' ' && start < len ) 284 | start++; 285 | 286 | start += stringLen; 287 | } 288 | } 289 | else 290 | { 291 | for ( int i = 0; i < indentSpaces; i++ ) 292 | os << " "; 293 | os << s << std::endl; 294 | } 295 | } 296 | 297 | } //namespace TCLAP 298 | #endif 299 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/SwitchArg.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: SwitchArg.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_SWITCH_ARG_H 25 | #define TCLAP_SWITCH_ARG_H 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | namespace TCLAP { 33 | 34 | /** 35 | * A simple switch argument. If the switch is set on the command line, then 36 | * the getValue method will return the opposite of the default value for the 37 | * switch. 38 | */ 39 | class SwitchArg : public Arg 40 | { 41 | protected: 42 | 43 | /** 44 | * The value of the switch. 45 | */ 46 | bool _value; 47 | 48 | /** 49 | * Used to support the reset() method so that ValueArg can be 50 | * reset to their constructed value. 51 | */ 52 | bool _default; 53 | 54 | public: 55 | 56 | /** 57 | * SwitchArg constructor. 58 | * \param flag - The one character flag that identifies this 59 | * argument on the command line. 60 | * \param name - A one word name for the argument. Can be 61 | * used as a long flag on the command line. 62 | * \param desc - A description of what the argument is for or 63 | * does. 64 | * \param def - The default value for this Switch. 65 | * \param v - An optional visitor. You probably should not 66 | * use this unless you have a very good reason. 67 | */ 68 | SwitchArg(const std::string& flag, 69 | const std::string& name, 70 | const std::string& desc, 71 | bool def = false, 72 | Visitor* v = NULL); 73 | 74 | 75 | /** 76 | * SwitchArg constructor. 77 | * \param flag - The one character flag that identifies this 78 | * argument on the command line. 79 | * \param name - A one word name for the argument. Can be 80 | * used as a long flag on the command line. 81 | * \param desc - A description of what the argument is for or 82 | * does. 83 | * \param parser - A CmdLine parser object to add this Arg to 84 | * \param def - The default value for this Switch. 85 | * \param v - An optional visitor. You probably should not 86 | * use this unless you have a very good reason. 87 | */ 88 | SwitchArg(const std::string& flag, 89 | const std::string& name, 90 | const std::string& desc, 91 | CmdLineInterface& parser, 92 | bool def = false, 93 | Visitor* v = NULL); 94 | 95 | 96 | /** 97 | * Handles the processing of the argument. 98 | * This re-implements the Arg version of this method to set the 99 | * _value of the argument appropriately. 100 | * \param i - Pointer the the current argument in the list. 101 | * \param args - Mutable list of strings. Passed 102 | * in from main(). 103 | */ 104 | virtual bool processArg(int* i, std::vector& args); 105 | 106 | /** 107 | * Checks a string to see if any of the chars in the string 108 | * match the flag for this Switch. 109 | */ 110 | bool combinedSwitchesMatch(std::string& combined); 111 | 112 | /** 113 | * Returns bool, whether or not the switch has been set. 114 | */ 115 | bool getValue(); 116 | 117 | virtual void reset(); 118 | 119 | private: 120 | /** 121 | * Checks to see if we've found the last match in 122 | * a combined string. 123 | */ 124 | bool lastCombined(std::string& combined); 125 | 126 | /** 127 | * Does the common processing of processArg. 128 | */ 129 | void commonProcessing(); 130 | }; 131 | 132 | ////////////////////////////////////////////////////////////////////// 133 | //BEGIN SwitchArg.cpp 134 | ////////////////////////////////////////////////////////////////////// 135 | inline SwitchArg::SwitchArg(const std::string& flag, 136 | const std::string& name, 137 | const std::string& desc, 138 | bool default_val, 139 | Visitor* v ) 140 | : Arg(flag, name, desc, false, false, v), 141 | _value( default_val ), 142 | _default( default_val ) 143 | { } 144 | 145 | inline SwitchArg::SwitchArg(const std::string& flag, 146 | const std::string& name, 147 | const std::string& desc, 148 | CmdLineInterface& parser, 149 | bool default_val, 150 | Visitor* v ) 151 | : Arg(flag, name, desc, false, false, v), 152 | _value( default_val ), 153 | _default(default_val) 154 | { 155 | parser.add( this ); 156 | } 157 | 158 | inline bool SwitchArg::getValue() { return _value; } 159 | 160 | inline bool SwitchArg::lastCombined(std::string& combinedSwitches ) 161 | { 162 | for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) 163 | if ( combinedSwitches[i] != Arg::blankChar() ) 164 | return false; 165 | 166 | return true; 167 | } 168 | 169 | inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches ) 170 | { 171 | // make sure this is actually a combined switch 172 | if ( combinedSwitches.length() > 0 && 173 | combinedSwitches[0] != Arg::flagStartString()[0] ) 174 | return false; 175 | 176 | // make sure it isn't a long name 177 | if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) == 178 | Arg::nameStartString() ) 179 | return false; 180 | 181 | // make sure the delimiter isn't in the string 182 | if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos ) 183 | return false; 184 | 185 | // ok, we're not specifying a ValueArg, so we know that we have 186 | // a combined switch list. 187 | for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) 188 | if ( _flag.length() > 0 && 189 | combinedSwitches[i] == _flag[0] && 190 | _flag[0] != Arg::flagStartString()[0] ) 191 | { 192 | // update the combined switches so this one is no longer present 193 | // this is necessary so that no unlabeled args are matched 194 | // later in the processing. 195 | //combinedSwitches.erase(i,1); 196 | combinedSwitches[i] = Arg::blankChar(); 197 | return true; 198 | } 199 | 200 | // none of the switches passed in the list match. 201 | return false; 202 | } 203 | 204 | inline void SwitchArg::commonProcessing() 205 | { 206 | if ( _xorSet ) 207 | throw(CmdLineParseException( 208 | "Mutually exclusive argument already set!", toString())); 209 | 210 | if ( _alreadySet ) 211 | throw(CmdLineParseException("Argument already set!", toString())); 212 | 213 | _alreadySet = true; 214 | 215 | if ( _value == true ) 216 | _value = false; 217 | else 218 | _value = true; 219 | 220 | _checkWithVisitor(); 221 | } 222 | 223 | inline bool SwitchArg::processArg(int *i, std::vector& args) 224 | { 225 | if ( _ignoreable && Arg::ignoreRest() ) 226 | return false; 227 | 228 | // if the whole string matches the flag or name string 229 | if ( argMatches( args[*i] ) ) 230 | { 231 | commonProcessing(); 232 | 233 | return true; 234 | } 235 | // if a substring matches the flag as part of a combination 236 | else if ( combinedSwitchesMatch( args[*i] ) ) 237 | { 238 | // check again to ensure we don't misinterpret 239 | // this as a MultiSwitchArg 240 | if ( combinedSwitchesMatch( args[*i] ) ) 241 | throw(CmdLineParseException("Argument already set!", 242 | toString())); 243 | 244 | commonProcessing(); 245 | 246 | // We only want to return true if we've found the last combined 247 | // match in the string, otherwise we return true so that other 248 | // switches in the combination will have a chance to match. 249 | return lastCombined( args[*i] ); 250 | } 251 | else 252 | return false; 253 | } 254 | 255 | inline void SwitchArg::reset() 256 | { 257 | Arg::reset(); 258 | _value = _default; 259 | } 260 | ////////////////////////////////////////////////////////////////////// 261 | //End SwitchArg.cpp 262 | ////////////////////////////////////////////////////////////////////// 263 | 264 | } //namespace TCLAP 265 | 266 | #endif 267 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/UnlabeledMultiArg.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: UnlabeledMultiArg.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot. 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | 23 | #ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H 24 | #define TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | namespace TCLAP { 33 | 34 | /** 35 | * Just like a MultiArg, except that the arguments are unlabeled. Basically, 36 | * this Arg will slurp up everything that hasn't been matched to another 37 | * Arg. 38 | */ 39 | template 40 | class UnlabeledMultiArg : public MultiArg 41 | { 42 | 43 | // If compiler has two stage name lookup (as gcc >= 3.4 does) 44 | // this is requried to prevent undef. symbols 45 | using MultiArg::_ignoreable; 46 | using MultiArg::_hasBlanks; 47 | using MultiArg::_extractValue; 48 | using MultiArg::_typeDesc; 49 | using MultiArg::_name; 50 | using MultiArg::_description; 51 | using MultiArg::_alreadySet; 52 | using MultiArg::toString; 53 | 54 | public: 55 | 56 | /** 57 | * Constructor. 58 | * \param name - The name of the Arg. Note that this is used for 59 | * identification, not as a long flag. 60 | * \param desc - A description of what the argument is for or 61 | * does. 62 | * \param req - Whether the argument is required on the command 63 | * line. 64 | * \param typeDesc - A short, human readable description of the 65 | * type that this object expects. This is used in the generation 66 | * of the USAGE statement. The goal is to be helpful to the end user 67 | * of the program. 68 | * \param ignoreable - Whether or not this argument can be ignored 69 | * using the "--" flag. 70 | * \param v - An optional visitor. You probably should not 71 | * use this unless you have a very good reason. 72 | */ 73 | UnlabeledMultiArg( const std::string& name, 74 | const std::string& desc, 75 | bool req, 76 | const std::string& typeDesc, 77 | bool ignoreable = false, 78 | Visitor* v = NULL ); 79 | /** 80 | * Constructor. 81 | * \param name - The name of the Arg. Note that this is used for 82 | * identification, not as a long flag. 83 | * \param desc - A description of what the argument is for or 84 | * does. 85 | * \param req - Whether the argument is required on the command 86 | * line. 87 | * \param typeDesc - A short, human readable description of the 88 | * type that this object expects. This is used in the generation 89 | * of the USAGE statement. The goal is to be helpful to the end user 90 | * of the program. 91 | * \param parser - A CmdLine parser object to add this Arg to 92 | * \param ignoreable - Whether or not this argument can be ignored 93 | * using the "--" flag. 94 | * \param v - An optional visitor. You probably should not 95 | * use this unless you have a very good reason. 96 | */ 97 | UnlabeledMultiArg( const std::string& name, 98 | const std::string& desc, 99 | bool req, 100 | const std::string& typeDesc, 101 | CmdLineInterface& parser, 102 | bool ignoreable = false, 103 | Visitor* v = NULL ); 104 | 105 | /** 106 | * Constructor. 107 | * \param name - The name of the Arg. Note that this is used for 108 | * identification, not as a long flag. 109 | * \param desc - A description of what the argument is for or 110 | * does. 111 | * \param req - Whether the argument is required on the command 112 | * line. 113 | * \param constraint - A pointer to a Constraint object used 114 | * to constrain this Arg. 115 | * \param ignoreable - Whether or not this argument can be ignored 116 | * using the "--" flag. 117 | * \param v - An optional visitor. You probably should not 118 | * use this unless you have a very good reason. 119 | */ 120 | UnlabeledMultiArg( const std::string& name, 121 | const std::string& desc, 122 | bool req, 123 | Constraint* constraint, 124 | bool ignoreable = false, 125 | Visitor* v = NULL ); 126 | 127 | /** 128 | * Constructor. 129 | * \param name - The name of the Arg. Note that this is used for 130 | * identification, not as a long flag. 131 | * \param desc - A description of what the argument is for or 132 | * does. 133 | * \param req - Whether the argument is required on the command 134 | * line. 135 | * \param constraint - A pointer to a Constraint object used 136 | * to constrain this Arg. 137 | * \param parser - A CmdLine parser object to add this Arg to 138 | * \param ignoreable - Whether or not this argument can be ignored 139 | * using the "--" flag. 140 | * \param v - An optional visitor. You probably should not 141 | * use this unless you have a very good reason. 142 | */ 143 | UnlabeledMultiArg( const std::string& name, 144 | const std::string& desc, 145 | bool req, 146 | Constraint* constraint, 147 | CmdLineInterface& parser, 148 | bool ignoreable = false, 149 | Visitor* v = NULL ); 150 | 151 | /** 152 | * Handles the processing of the argument. 153 | * This re-implements the Arg version of this method to set the 154 | * _value of the argument appropriately. It knows the difference 155 | * between labeled and unlabeled. 156 | * \param i - Pointer the the current argument in the list. 157 | * \param args - Mutable list of strings. Passed from main(). 158 | */ 159 | virtual bool processArg(int* i, std::vector& args); 160 | 161 | /** 162 | * Returns the a short id string. Used in the usage. 163 | * \param val - value to be used. 164 | */ 165 | virtual std::string shortID(const std::string& val="val") const; 166 | 167 | /** 168 | * Returns the a long id string. Used in the usage. 169 | * \param val - value to be used. 170 | */ 171 | virtual std::string longID(const std::string& val="val") const; 172 | 173 | /** 174 | * Opertor ==. 175 | * \param a - The Arg to be compared to this. 176 | */ 177 | virtual bool operator==(const Arg& a) const; 178 | 179 | /** 180 | * Pushes this to back of list rather than front. 181 | * \param argList - The list this should be added to. 182 | */ 183 | virtual void addToList( std::list& argList ) const; 184 | }; 185 | 186 | template 187 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 188 | const std::string& desc, 189 | bool req, 190 | const std::string& typeDesc, 191 | bool ignoreable, 192 | Visitor* v) 193 | : MultiArg("", name, desc, req, typeDesc, v) 194 | { 195 | _ignoreable = ignoreable; 196 | OptionalUnlabeledTracker::check(true, toString()); 197 | } 198 | 199 | template 200 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 201 | const std::string& desc, 202 | bool req, 203 | const std::string& typeDesc, 204 | CmdLineInterface& parser, 205 | bool ignoreable, 206 | Visitor* v) 207 | : MultiArg("", name, desc, req, typeDesc, v) 208 | { 209 | _ignoreable = ignoreable; 210 | OptionalUnlabeledTracker::check(true, toString()); 211 | parser.add( this ); 212 | } 213 | 214 | 215 | template 216 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 217 | const std::string& desc, 218 | bool req, 219 | Constraint* constraint, 220 | bool ignoreable, 221 | Visitor* v) 222 | : MultiArg("", name, desc, req, constraint, v) 223 | { 224 | _ignoreable = ignoreable; 225 | OptionalUnlabeledTracker::check(true, toString()); 226 | } 227 | 228 | template 229 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 230 | const std::string& desc, 231 | bool req, 232 | Constraint* constraint, 233 | CmdLineInterface& parser, 234 | bool ignoreable, 235 | Visitor* v) 236 | : MultiArg("", name, desc, req, constraint, v) 237 | { 238 | _ignoreable = ignoreable; 239 | OptionalUnlabeledTracker::check(true, toString()); 240 | parser.add( this ); 241 | } 242 | 243 | 244 | template 245 | bool UnlabeledMultiArg::processArg(int *i, std::vector& args) 246 | { 247 | 248 | if ( _hasBlanks( args[*i] ) ) 249 | return false; 250 | 251 | // never ignore an unlabeled multi arg 252 | 253 | 254 | // always take the first value, regardless of the start string 255 | _extractValue( args[(*i)] ); 256 | 257 | /* 258 | // continue taking args until we hit the end or a start string 259 | while ( (unsigned int)(*i)+1 < args.size() && 260 | args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && 261 | args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) 262 | _extractValue( args[++(*i)] ); 263 | */ 264 | 265 | _alreadySet = true; 266 | 267 | return true; 268 | } 269 | 270 | template 271 | std::string UnlabeledMultiArg::shortID(const std::string& val) const 272 | { 273 | static_cast(val); // Ignore input, don't warn 274 | return std::string("<") + _typeDesc + "> ..."; 275 | } 276 | 277 | template 278 | std::string UnlabeledMultiArg::longID(const std::string& val) const 279 | { 280 | static_cast(val); // Ignore input, don't warn 281 | return std::string("<") + _typeDesc + "> (accepted multiple times)"; 282 | } 283 | 284 | template 285 | bool UnlabeledMultiArg::operator==(const Arg& a) const 286 | { 287 | if ( _name == a.getName() || _description == a.getDescription() ) 288 | return true; 289 | else 290 | return false; 291 | } 292 | 293 | template 294 | void UnlabeledMultiArg::addToList( std::list& argList ) const 295 | { 296 | argList.push_back( const_cast(static_cast(this)) ); 297 | } 298 | 299 | } 300 | 301 | #endif 302 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/ValuesConstraint.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ValuesConstraint.h 6 | * 7 | * Copyright (c) 2005, Michael E. Smoot 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_VALUESCONSTRAINT_H 24 | #define TCLAP_VALUESCONSTRAINT_H 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #ifdef HAVE_CONFIG_H 31 | #include 32 | #else 33 | #define HAVE_SSTREAM 34 | #endif 35 | 36 | #if defined(HAVE_SSTREAM) 37 | #include 38 | #elif defined(HAVE_STRSTREAM) 39 | #include 40 | #else 41 | #error "Need a stringstream (sstream or strstream) to compile!" 42 | #endif 43 | 44 | namespace TCLAP { 45 | 46 | /** 47 | * A Constraint that constrains the Arg to only those values specified 48 | * in the constraint. 49 | */ 50 | template 51 | class ValuesConstraint : public Constraint 52 | { 53 | 54 | public: 55 | 56 | /** 57 | * Constructor. 58 | * \param allowed - vector of allowed values. 59 | */ 60 | ValuesConstraint(std::vector& allowed); 61 | 62 | /** 63 | * Virtual destructor. 64 | */ 65 | virtual ~ValuesConstraint() {} 66 | 67 | /** 68 | * Returns a description of the Constraint. 69 | */ 70 | virtual std::string description() const; 71 | 72 | /** 73 | * Returns the short ID for the Constraint. 74 | */ 75 | virtual std::string shortID() const; 76 | 77 | /** 78 | * The method used to verify that the value parsed from the command 79 | * line meets the constraint. 80 | * \param value - The value that will be checked. 81 | */ 82 | virtual bool check(const T& value) const; 83 | 84 | protected: 85 | 86 | /** 87 | * The list of valid values. 88 | */ 89 | std::vector _allowed; 90 | 91 | /** 92 | * The string used to describe the allowed values of this constraint. 93 | */ 94 | std::string _typeDesc; 95 | 96 | }; 97 | 98 | template 99 | ValuesConstraint::ValuesConstraint(std::vector& allowed) 100 | : _allowed(allowed), 101 | _typeDesc("") 102 | { 103 | for ( unsigned int i = 0; i < _allowed.size(); i++ ) 104 | { 105 | 106 | #if defined(HAVE_SSTREAM) 107 | std::ostringstream os; 108 | #elif defined(HAVE_STRSTREAM) 109 | std::ostrstream os; 110 | #else 111 | #error "Need a stringstream (sstream or strstream) to compile!" 112 | #endif 113 | 114 | os << _allowed[i]; 115 | 116 | std::string temp( os.str() ); 117 | 118 | if ( i > 0 ) 119 | _typeDesc += "|"; 120 | _typeDesc += temp; 121 | } 122 | } 123 | 124 | template 125 | bool ValuesConstraint::check( const T& val ) const 126 | { 127 | if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() ) 128 | return false; 129 | else 130 | return true; 131 | } 132 | 133 | template 134 | std::string ValuesConstraint::shortID() const 135 | { 136 | return _typeDesc; 137 | } 138 | 139 | template 140 | std::string ValuesConstraint::description() const 141 | { 142 | return _typeDesc; 143 | } 144 | 145 | 146 | } //namespace TCLAP 147 | #endif 148 | 149 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/VersionVisitor.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: VersionVisitor.h 6 | * 7 | * Copyright (c) 2003, Michael E. Smoot . 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_VERSION_VISITOR_H 25 | #define TCLAP_VERSION_VISITOR_H 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | namespace TCLAP { 32 | 33 | /** 34 | * A Vistor that will call the version method of the given CmdLineOutput 35 | * for the specified CmdLine object and then exit. 36 | */ 37 | class VersionVisitor: public Visitor 38 | { 39 | private: 40 | /** 41 | * Prevent accidental copying 42 | */ 43 | VersionVisitor(const VersionVisitor& rhs); 44 | VersionVisitor& operator=(const VersionVisitor& rhs); 45 | 46 | protected: 47 | 48 | /** 49 | * The CmdLine of interest. 50 | */ 51 | CmdLineInterface* _cmd; 52 | 53 | /** 54 | * The output object. 55 | */ 56 | CmdLineOutput** _out; 57 | 58 | public: 59 | 60 | /** 61 | * Constructor. 62 | * \param cmd - The CmdLine the output is generated for. 63 | * \param out - The type of output. 64 | */ 65 | VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out ) 66 | : Visitor(), _cmd( cmd ), _out( out ) { } 67 | 68 | /** 69 | * Calls the version method of the output object using the 70 | * specified CmdLine. 71 | */ 72 | void visit() { 73 | (*_out)->version(*_cmd); 74 | throw ExitException(0); 75 | } 76 | 77 | }; 78 | 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/Visitor.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: Visitor.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * All rights reverved. 8 | * 9 | * See the file COPYING in the top directory of this distribution for 10 | * more information. 11 | * 12 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 13 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 15 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 18 | * DEALINGS IN THE SOFTWARE. 19 | * 20 | *****************************************************************************/ 21 | 22 | 23 | #ifndef TCLAP_VISITOR_H 24 | #define TCLAP_VISITOR_H 25 | 26 | namespace TCLAP { 27 | 28 | /** 29 | * A base class that defines the interface for visitors. 30 | */ 31 | class Visitor 32 | { 33 | public: 34 | 35 | /** 36 | * Constructor. Does nothing. 37 | */ 38 | Visitor() { } 39 | 40 | /** 41 | * Destructor. Does nothing. 42 | */ 43 | virtual ~Visitor() { } 44 | 45 | /** 46 | * Does nothing. Should be overridden by child. 47 | */ 48 | virtual void visit() { } 49 | }; 50 | 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/XorHandler.h: -------------------------------------------------------------------------------- 1 | 2 | /****************************************************************************** 3 | * 4 | * file: XorHandler.h 5 | * 6 | * Copyright (c) 2003, Michael E. Smoot . 7 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_XORHANDLER_H 24 | #define TCLAP_XORHANDLER_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace TCLAP { 33 | 34 | /** 35 | * This class handles lists of Arg's that are to be XOR'd on the command 36 | * line. This is used by CmdLine and you shouldn't ever use it. 37 | */ 38 | class XorHandler 39 | { 40 | protected: 41 | 42 | /** 43 | * The list of of lists of Arg's to be or'd together. 44 | */ 45 | std::vector< std::vector > _orList; 46 | 47 | public: 48 | 49 | /** 50 | * Constructor. Does nothing. 51 | */ 52 | XorHandler( ) : _orList(std::vector< std::vector >()) {} 53 | 54 | /** 55 | * Add a list of Arg*'s that will be orred together. 56 | * \param ors - list of Arg* that will be xor'd. 57 | */ 58 | void add( std::vector& ors ); 59 | 60 | /** 61 | * Checks whether the specified Arg is in one of the xor lists and 62 | * if it does match one, returns the size of the xor list that the 63 | * Arg matched. If the Arg matches, then it also sets the rest of 64 | * the Arg's in the list. You shouldn't use this. 65 | * \param a - The Arg to be checked. 66 | */ 67 | int check( const Arg* a ); 68 | 69 | /** 70 | * Returns the XOR specific short usage. 71 | */ 72 | std::string shortUsage(); 73 | 74 | /** 75 | * Prints the XOR specific long usage. 76 | * \param os - Stream to print to. 77 | */ 78 | void printLongUsage(std::ostream& os); 79 | 80 | /** 81 | * Simply checks whether the Arg is contained in one of the arg 82 | * lists. 83 | * \param a - The Arg to be checked. 84 | */ 85 | bool contains( const Arg* a ); 86 | 87 | std::vector< std::vector >& getXorList(); 88 | 89 | }; 90 | 91 | 92 | ////////////////////////////////////////////////////////////////////// 93 | //BEGIN XOR.cpp 94 | ////////////////////////////////////////////////////////////////////// 95 | inline void XorHandler::add( std::vector& ors ) 96 | { 97 | _orList.push_back( ors ); 98 | } 99 | 100 | inline int XorHandler::check( const Arg* a ) 101 | { 102 | // iterate over each XOR list 103 | for ( int i = 0; static_cast(i) < _orList.size(); i++ ) 104 | { 105 | // if the XOR list contains the arg.. 106 | ArgVectorIterator ait = std::find( _orList[i].begin(), 107 | _orList[i].end(), a ); 108 | if ( ait != _orList[i].end() ) 109 | { 110 | // first check to see if a mutually exclusive switch 111 | // has not already been set 112 | for ( ArgVectorIterator it = _orList[i].begin(); 113 | it != _orList[i].end(); 114 | it++ ) 115 | if ( a != (*it) && (*it)->isSet() ) 116 | throw(CmdLineParseException( 117 | "Mutually exclusive argument already set!", 118 | (*it)->toString())); 119 | 120 | // go through and set each arg that is not a 121 | for ( ArgVectorIterator it = _orList[i].begin(); 122 | it != _orList[i].end(); 123 | it++ ) 124 | if ( a != (*it) ) 125 | (*it)->xorSet(); 126 | 127 | // return the number of required args that have now been set 128 | if ( (*ait)->allowMore() ) 129 | return 0; 130 | else 131 | return static_cast(_orList[i].size()); 132 | } 133 | } 134 | 135 | if ( a->isRequired() ) 136 | return 1; 137 | else 138 | return 0; 139 | } 140 | 141 | inline bool XorHandler::contains( const Arg* a ) 142 | { 143 | for ( int i = 0; static_cast(i) < _orList.size(); i++ ) 144 | for ( ArgVectorIterator it = _orList[i].begin(); 145 | it != _orList[i].end(); 146 | it++ ) 147 | if ( a == (*it) ) 148 | return true; 149 | 150 | return false; 151 | } 152 | 153 | inline std::vector< std::vector >& XorHandler::getXorList() 154 | { 155 | return _orList; 156 | } 157 | 158 | 159 | 160 | ////////////////////////////////////////////////////////////////////// 161 | //END XOR.cpp 162 | ////////////////////////////////////////////////////////////////////// 163 | 164 | } //namespace TCLAP 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /components/mkspiffs/tclap/ZshCompletionOutput.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ZshCompletionOutput.h 6 | * 7 | * Copyright (c) 2006, Oliver Kiddle 8 | * All rights reverved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | #ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H 24 | #define TCLAP_ZSHCOMPLETIONOUTPUT_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace TCLAP { 38 | 39 | /** 40 | * A class that generates a Zsh completion function as output from the usage() 41 | * method for the given CmdLine and its Args. 42 | */ 43 | class ZshCompletionOutput : public CmdLineOutput 44 | { 45 | 46 | public: 47 | 48 | ZshCompletionOutput(); 49 | 50 | /** 51 | * Prints the usage to stdout. Can be overridden to 52 | * produce alternative behavior. 53 | * \param c - The CmdLine object the output is generated for. 54 | */ 55 | virtual void usage(CmdLineInterface& c); 56 | 57 | /** 58 | * Prints the version to stdout. Can be overridden 59 | * to produce alternative behavior. 60 | * \param c - The CmdLine object the output is generated for. 61 | */ 62 | virtual void version(CmdLineInterface& c); 63 | 64 | /** 65 | * Prints (to stderr) an error message, short usage 66 | * Can be overridden to produce alternative behavior. 67 | * \param c - The CmdLine object the output is generated for. 68 | * \param e - The ArgException that caused the failure. 69 | */ 70 | virtual void failure(CmdLineInterface& c, 71 | ArgException& e ); 72 | 73 | protected: 74 | 75 | void basename( std::string& s ); 76 | void quoteSpecialChars( std::string& s ); 77 | 78 | std::string getMutexList( CmdLineInterface& _cmd, Arg* a ); 79 | void printOption( Arg* it, std::string mutex ); 80 | void printArg( Arg* it ); 81 | 82 | std::map common; 83 | char theDelimiter; 84 | }; 85 | 86 | ZshCompletionOutput::ZshCompletionOutput() 87 | : common(std::map()), 88 | theDelimiter('=') 89 | { 90 | common["host"] = "_hosts"; 91 | common["hostname"] = "_hosts"; 92 | common["file"] = "_files"; 93 | common["filename"] = "_files"; 94 | common["user"] = "_users"; 95 | common["username"] = "_users"; 96 | common["directory"] = "_directories"; 97 | common["path"] = "_directories"; 98 | common["url"] = "_urls"; 99 | } 100 | 101 | inline void ZshCompletionOutput::version(CmdLineInterface& _cmd) 102 | { 103 | std::cout << _cmd.getVersion() << std::endl; 104 | } 105 | 106 | inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd ) 107 | { 108 | std::list argList = _cmd.getArgList(); 109 | std::string progName = _cmd.getProgramName(); 110 | std::string xversion = _cmd.getVersion(); 111 | theDelimiter = _cmd.getDelimiter(); 112 | basename(progName); 113 | 114 | std::cout << "#compdef " << progName << std::endl << std::endl << 115 | "# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl << 116 | "_arguments -s -S"; 117 | 118 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 119 | { 120 | if ( (*it)->shortID().at(0) == '<' ) 121 | printArg((*it)); 122 | else if ( (*it)->getFlag() != "-" ) 123 | printOption((*it), getMutexList(_cmd, *it)); 124 | } 125 | 126 | std::cout << std::endl; 127 | } 128 | 129 | inline void ZshCompletionOutput::failure( CmdLineInterface& _cmd, 130 | ArgException& e ) 131 | { 132 | static_cast(_cmd); // unused 133 | std::cout << e.what() << std::endl; 134 | } 135 | 136 | inline void ZshCompletionOutput::quoteSpecialChars( std::string& s ) 137 | { 138 | size_t idx = s.find_last_of(':'); 139 | while ( idx != std::string::npos ) 140 | { 141 | s.insert(idx, 1, '\\'); 142 | idx = s.find_last_of(':', idx); 143 | } 144 | idx = s.find_last_of('\''); 145 | while ( idx != std::string::npos ) 146 | { 147 | s.insert(idx, "'\\'"); 148 | if (idx == 0) 149 | idx = std::string::npos; 150 | else 151 | idx = s.find_last_of('\'', --idx); 152 | } 153 | } 154 | 155 | inline void ZshCompletionOutput::basename( std::string& s ) 156 | { 157 | size_t p = s.find_last_of('/'); 158 | if ( p != std::string::npos ) 159 | { 160 | s.erase(0, p + 1); 161 | } 162 | } 163 | 164 | inline void ZshCompletionOutput::printArg(Arg* a) 165 | { 166 | static int count = 1; 167 | 168 | std::cout << " \\" << std::endl << " '"; 169 | if ( a->acceptsMultipleValues() ) 170 | std::cout << '*'; 171 | else 172 | std::cout << count++; 173 | std::cout << ':'; 174 | if ( !a->isRequired() ) 175 | std::cout << ':'; 176 | 177 | std::cout << a->getName() << ':'; 178 | std::map::iterator compArg = common.find(a->getName()); 179 | if ( compArg != common.end() ) 180 | { 181 | std::cout << compArg->second; 182 | } 183 | else 184 | { 185 | std::cout << "_guard \"^-*\" " << a->getName(); 186 | } 187 | std::cout << '\''; 188 | } 189 | 190 | inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex) 191 | { 192 | std::string flag = a->flagStartChar() + a->getFlag(); 193 | std::string name = a->nameStartString() + a->getName(); 194 | std::string desc = a->getDescription(); 195 | 196 | // remove full stop and capitalisation from description as 197 | // this is the convention for zsh function 198 | if (!desc.compare(0, 12, "(required) ")) 199 | { 200 | desc.erase(0, 12); 201 | } 202 | if (!desc.compare(0, 15, "(OR required) ")) 203 | { 204 | desc.erase(0, 15); 205 | } 206 | size_t len = desc.length(); 207 | if (len && desc.at(--len) == '.') 208 | { 209 | desc.erase(len); 210 | } 211 | if (len) 212 | { 213 | desc.replace(0, 1, 1, tolower(desc.at(0))); 214 | } 215 | 216 | std::cout << " \\" << std::endl << " '" << mutex; 217 | 218 | if ( a->getFlag().empty() ) 219 | { 220 | std::cout << name; 221 | } 222 | else 223 | { 224 | std::cout << "'{" << flag << ',' << name << "}'"; 225 | } 226 | if ( theDelimiter == '=' && a->isValueRequired() ) 227 | std::cout << "=-"; 228 | quoteSpecialChars(desc); 229 | std::cout << '[' << desc << ']'; 230 | 231 | if ( a->isValueRequired() ) 232 | { 233 | std::string arg = a->shortID(); 234 | arg.erase(0, arg.find_last_of(theDelimiter) + 1); 235 | if ( arg.at(arg.length()-1) == ']' ) 236 | arg.erase(arg.length()-1); 237 | if ( arg.at(arg.length()-1) == ']' ) 238 | { 239 | arg.erase(arg.length()-1); 240 | } 241 | if ( arg.at(0) == '<' ) 242 | { 243 | arg.erase(arg.length()-1); 244 | arg.erase(0, 1); 245 | } 246 | size_t p = arg.find('|'); 247 | if ( p != std::string::npos ) 248 | { 249 | do 250 | { 251 | arg.replace(p, 1, 1, ' '); 252 | } 253 | while ( (p = arg.find_first_of('|', p)) != std::string::npos ); 254 | quoteSpecialChars(arg); 255 | std::cout << ": :(" << arg << ')'; 256 | } 257 | else 258 | { 259 | std::cout << ':' << arg; 260 | std::map::iterator compArg = common.find(arg); 261 | if ( compArg != common.end() ) 262 | { 263 | std::cout << ':' << compArg->second; 264 | } 265 | } 266 | } 267 | 268 | std::cout << '\''; 269 | } 270 | 271 | inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Arg* a) 272 | { 273 | XorHandler xorHandler = _cmd.getXorHandler(); 274 | std::vector< std::vector > xorList = xorHandler.getXorList(); 275 | 276 | if (a->getName() == "help" || a->getName() == "version") 277 | { 278 | return "(-)"; 279 | } 280 | 281 | std::ostringstream list; 282 | if ( a->acceptsMultipleValues() ) 283 | { 284 | list << '*'; 285 | } 286 | 287 | for ( int i = 0; static_cast(i) < xorList.size(); i++ ) 288 | { 289 | for ( ArgVectorIterator it = xorList[i].begin(); 290 | it != xorList[i].end(); 291 | it++) 292 | if ( a == (*it) ) 293 | { 294 | list << '('; 295 | for ( ArgVectorIterator iu = xorList[i].begin(); 296 | iu != xorList[i].end(); 297 | iu++ ) 298 | { 299 | bool notCur = (*iu) != a; 300 | bool hasFlag = !(*iu)->getFlag().empty(); 301 | if ( iu != xorList[i].begin() && (notCur || hasFlag) ) 302 | list << ' '; 303 | if (hasFlag) 304 | list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' '; 305 | if ( notCur || hasFlag ) 306 | list << (*iu)->nameStartString() << (*iu)->getName(); 307 | } 308 | list << ')'; 309 | return list.str(); 310 | } 311 | } 312 | 313 | // wasn't found in xor list 314 | if (!a->getFlag().empty()) { 315 | list << "(" << a->flagStartChar() << a->getFlag() << ' ' << 316 | a->nameStartString() << a->getName() << ')'; 317 | } 318 | 319 | return list.str(); 320 | } 321 | 322 | } //namespace TCLAP 323 | #endif 324 | -------------------------------------------------------------------------------- /components/spiffs/Kconfig: -------------------------------------------------------------------------------- 1 | menu "SPIFFS Configuration" 2 | 3 | config SPIFFS_MAX_PARTITIONS 4 | int "Maximum Number of Partitions" 5 | default 3 6 | range 1 10 7 | help 8 | Define maximum number of partitions that can be mounted. 9 | 10 | menu "SPIFFS Cache Configuration" 11 | config SPIFFS_CACHE 12 | bool "Enable SPIFFS Cache" 13 | default "y" 14 | help 15 | Enables/disable memory read caching of nucleus file system 16 | operations. 17 | 18 | config SPIFFS_CACHE_WR 19 | bool "Enable SPIFFS Write Caching" 20 | default "y" 21 | depends on SPIFFS_CACHE 22 | help 23 | Enables memory write caching for file descriptors in hydrogen. 24 | 25 | config SPIFFS_CACHE_STATS 26 | bool "Enable SPIFFS Cache Statistics" 27 | default "n" 28 | depends on SPIFFS_CACHE 29 | help 30 | Enable/disable statistics on caching. Debug/test purpose only. 31 | 32 | endmenu 33 | 34 | config SPIFFS_PAGE_CHECK 35 | bool "Enable SPIFFS Page Check" 36 | default "y" 37 | help 38 | Always check header of each accessed page to ensure consistent state. 39 | If enabled it will increase number of reads from flash, especially 40 | if cache is disabled. 41 | 42 | config SPIFFS_GC_MAX_RUNS 43 | int "Set Maximum GC Runs" 44 | default 10 45 | range 1 255 46 | help 47 | Define maximum number of GC runs to perform to reach desired free pages. 48 | 49 | config SPIFFS_GC_STATS 50 | bool "Enable SPIFFS GC Statistics" 51 | default "n" 52 | help 53 | Enable/disable statistics on gc. Debug/test purpose only. 54 | 55 | config SPIFFS_PAGE_SIZE 56 | int "SPIFFS logical page size" 57 | default 256 58 | range 256 1024 59 | help 60 | Logical page size of SPIFFS partition, in bytes. Must be multiple 61 | of flash page size (which is usually 256 bytes). 62 | Larger page sizes reduce overhead when storing large files, and 63 | improve filesystem performance when reading large files. 64 | Smaller page sizes reduce overhead when storing small (< page size) 65 | files. 66 | 67 | config SPIFFS_OBJ_NAME_LEN 68 | int "Set SPIFFS Maximum Name Length" 69 | default 32 70 | range 1 256 71 | help 72 | Object name maximum length. Note that this length include the 73 | zero-termination character, meaning maximum string of characters 74 | can at most be SPIFFS_OBJ_NAME_LEN - 1. 75 | 76 | SPIFFS_OBJ_NAME_LEN + SPIFFS_META_LENGTH should not exceed 77 | SPIFFS_PAGE_SIZE - 64. 78 | 79 | config SPIFFS_USE_MAGIC 80 | bool "Enable SPIFFS Filesystem Magic" 81 | default "y" 82 | help 83 | Enable this to have an identifiable spiffs filesystem. 84 | This will look for a magic in all sectors to determine if this 85 | is a valid spiffs system or not at mount time. 86 | 87 | config SPIFFS_USE_MAGIC_LENGTH 88 | bool "Enable SPIFFS Filesystem Length Magic" 89 | default "y" 90 | depends on SPIFFS_USE_MAGIC 91 | help 92 | If this option is enabled, the magic will also be dependent 93 | on the length of the filesystem. For example, a filesystem 94 | configured and formatted for 4 megabytes will not be accepted 95 | for mounting with a configuration defining the filesystem as 2 megabytes. 96 | 97 | config SPIFFS_META_LENGTH 98 | int "Size of per-file metadata field" 99 | default 5 100 | range 0 64 101 | help 102 | This option sets the number of extra bytes stored in the file header. 103 | These bytes can be used in an application-specific manner. 104 | Set this to at least 4 bytes to enable support for saving file 105 | modification time. 106 | 107 | SPIFFS_OBJ_NAME_LEN + SPIFFS_META_LENGTH should not exceed 108 | SPIFFS_PAGE_SIZE - 64. 109 | 110 | config SPIFFS_USE_MTIME 111 | bool "Save file modification time" 112 | default "y" 113 | depends on (!SPIFFS_USE_DIR && SPIFFS_META_LENGTH >= 4) || (SPIFFS_USE_DIR && SPIFFS_META_LENGTH >= 5) 114 | help 115 | If enabled, then the first 4 bytes of per-file metadata will be used 116 | to store file modification time (mtime), accessible through 117 | stat/fstat functions. 118 | Modification time is updated when the file is opened. 119 | 120 | config SPIFFS_USE_DIR 121 | bool "Enable directories" 122 | default "y" 123 | depends on SPIFFS_META_LENGTH >= 1 124 | help 125 | If enabled, directory support will be enabled in spiffs. 126 | Directory create/remove functions will be accessible through 127 | mkdir/rmdir functions. 128 | One additional byte of per-file metadata will be used 129 | to store file the file type (regular file/directory) 130 | 131 | menu "Debug Configuration" 132 | 133 | config SPIFFS_DBG 134 | bool "Enable general SPIFFS debug" 135 | default "n" 136 | help 137 | Enabling this option will print general debug mesages to the console. 138 | 139 | config SPIFFS_API_DBG 140 | bool "Enable SPIFFS API debug" 141 | default "n" 142 | help 143 | Enabling this option will print API debug mesages to the console. 144 | 145 | config SPIFFS_GC_DBG 146 | bool "Enable SPIFFS Garbage Cleaner debug" 147 | default "n" 148 | help 149 | Enabling this option will print GC debug mesages to the console. 150 | 151 | config SPIFFS_CACHE_DBG 152 | bool "Enable SPIFFS Cache debug" 153 | default "n" 154 | depends on SPIFFS_CACHE 155 | help 156 | Enabling this option will print cache debug mesages to the console. 157 | 158 | config SPIFFS_CHECK_DBG 159 | bool "Enable SPIFFS Filesystem Check debug" 160 | default "n" 161 | help 162 | Enabling this option will print Filesystem Check debug mesages 163 | to the console. 164 | 165 | config SPIFFS_TEST_VISUALISATION 166 | bool "Enable SPIFFS Filesystem Visualization" 167 | default "n" 168 | help 169 | Enable this option to enable SPIFFS_vis function in the API. 170 | 171 | endmenu 172 | 173 | endmenu 174 | -------------------------------------------------------------------------------- /components/spiffs/component.mk: -------------------------------------------------------------------------------- 1 | COMPONENT_ADD_INCLUDEDIRS := include 2 | COMPONENT_PRIV_INCLUDEDIRS := spiffs/src 3 | COMPONENT_SRCDIRS := . spiffs/src 4 | 5 | COMPONENT_SUBMODULES := spiffs 6 | -------------------------------------------------------------------------------- /components/spiffs/include/esp_spiffs.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef _ESP_SPIFFS_H_ 16 | #define _ESP_SPIFFS_H_ 17 | 18 | #include 19 | #include "esp_err.h" 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | /** 26 | * @brief Configuration structure for esp_vfs_spiffs_register 27 | */ 28 | typedef struct { 29 | const char* base_path; /*!< File path prefix associated with the filesystem. */ 30 | const char* partition_label; /*!< Optional, label of SPIFFS partition to use. If set to NULL, first partition with subtype=spiffs will be used. */ 31 | size_t max_files; /*!< Maximum files that could be open at the same time. */ 32 | bool format_if_mount_failed; /*!< If true, it will format the file system if it fails to mount. */ 33 | } esp_vfs_spiffs_conf_t; 34 | 35 | /** 36 | * Register and mount SPIFFS to VFS with given path prefix. 37 | * 38 | * @param conf Pointer to esp_vfs_spiffs_conf_t configuration structure 39 | * 40 | * @return 41 | * - ESP_OK if success 42 | * - ESP_ERR_NO_MEM if objects could not be allocated 43 | * - ESP_ERR_INVALID_STATE if already mounted or partition is encrypted 44 | * - ESP_ERR_NOT_FOUND if partition for SPIFFS was not found 45 | * - ESP_FAIL if mount or format fails 46 | */ 47 | esp_err_t esp_vfs_spiffs_register(const esp_vfs_spiffs_conf_t * conf); 48 | 49 | /** 50 | * Unregister and unmount SPIFFS from VFS 51 | * 52 | * @param partition_label Optional, label of the partition to unregister. 53 | * If not specified, first partition with subtype=spiffs is used. 54 | * 55 | * @return 56 | * - ESP_OK if successful 57 | * - ESP_ERR_INVALID_STATE already unregistered 58 | */ 59 | esp_err_t esp_vfs_spiffs_unregister(const char* partition_label); 60 | 61 | /** 62 | * Check if SPIFFS is mounted 63 | * 64 | * @param partition_label Optional, label of the partition to check. 65 | * If not specified, first partition with subtype=spiffs is used. 66 | * 67 | * @return 68 | * - true if mounted 69 | * - false if not mounted 70 | */ 71 | bool esp_spiffs_mounted(const char* partition_label); 72 | 73 | /** 74 | * Format the SPIFFS partition 75 | * 76 | * @param partition_label Optional, label of the partition to format. 77 | * If not specified, first partition with subtype=spiffs is used. 78 | * @return 79 | * - ESP_OK if successful 80 | * - ESP_FAIL on error 81 | */ 82 | esp_err_t esp_spiffs_format(const char* partition_label); 83 | 84 | /** 85 | * Get information for SPIFFS 86 | * 87 | * @param partition_label Optional, label of the partition to get info for. 88 | * If not specified, first partition with subtype=spiffs is used. 89 | * @param[out] total_bytes Size of the file system 90 | * @param[out] used_bytes Current used bytes in the file system 91 | * 92 | * @return 93 | * - ESP_OK if success 94 | * - ESP_ERR_INVALID_STATE if not mounted 95 | */ 96 | esp_err_t esp_spiffs_info(const char* partition_label, size_t *total_bytes, size_t *used_bytes); 97 | 98 | #ifdef __cplusplus 99 | } 100 | #endif 101 | 102 | #endif /* _ESP_SPIFFS_H_ */ 103 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | compiler: 4 | - gcc 5 | 6 | before_script: 7 | 8 | script: make all && make clean && make test && make build-all && make clean test FLAGS=-DSPIFFS_OBJ_META_LEN=8 9 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/FUZZING.md: -------------------------------------------------------------------------------- 1 | # Fuzzing SPIFFS 2 | 3 | The SPIFFS test suite includes a test program designed for fuzzing with 4 | [AFL](http://lcamtuf.coredump.cx/afl/). This automatically exercises the 5 | SPIFFS API and verifies that the file system does not crash or interact incorrectly 6 | with the flash chip. 7 | 8 | There are two steps to fuzzing. The first is to build the test suite with 9 | the AFL version of gcc. The CC variable should point to your copy of afl-gcc. 10 | 11 | ``` 12 | make clean test CC=/usr/local/bin/afl-gcc 13 | ``` 14 | 15 | There is a new test `afl_test` that reads from stdin a list of commands 16 | and arguments. These are interpreted and executed on the API. The `afltests` 17 | directory contains a number of test cases that can be fed to the `afl_test` test. 18 | 19 | 20 | The second is to run this test suite under afl as follows (where findings is 21 | the output directory): 22 | 23 | ``` 24 | afl-fuzz -i afltests -o findings ./build/linux_spiffs_test -f afl_test 25 | ``` 26 | 27 | This run will take hours (or days) and will (hopefully) not find any crashes. 28 | If a crash (or hang) is found, then the input file that caused the crash is 29 | saved. This allows the specific test case to be debugged. 30 | 31 | ## Reducing the size of the file 32 | 33 | AFL comes with `afl-tmin` which can reduce the size of the test input file to 34 | make it easier to debug. 35 | 36 | ``` 37 | afl-tmin -i findings/crashes/ -o smalltest -- build/linux_spiffs_test -f afl_test 38 | ``` 39 | 40 | This will write a short version of the testcase file to `smalltest`. This can then be 41 | fed into the test program for debugging: 42 | 43 | ``` 44 | build/linux_spiffs_test -f afl_test < smalltest 45 | ``` 46 | 47 | This should still crash, but allows it to be run under a debugger. 48 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2017 Peter Andersson (pelleplutt1976gmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/README.md: -------------------------------------------------------------------------------- 1 | # SPIFFS (SPI Flash File System) 2 | **V0.3.7** 3 | 4 | [![Build Status](https://travis-ci.org/pellepl/spiffs.svg?branch=master)](https://travis-ci.org/pellepl/spiffs) 5 | 6 | Copyright (c) 2013-2017 Peter Andersson (pelleplutt1976 at gmail.com) 7 | 8 | For legal stuff, see [LICENSE](https://github.com/pellepl/spiffs/blob/master/LICENSE). Basically, you may do whatever you want with the source. Use, modify, sell, print it out, roll it and smoke it - as long as I won't be held responsible. 9 | 10 | Love to hear feedback though! 11 | 12 | 13 | ## INTRODUCTION 14 | 15 | Spiffs is a file system intended for SPI NOR flash devices on embedded targets. 16 | 17 | Spiffs is designed with following characteristics in mind: 18 | - Small (embedded) targets, sparse RAM without heap 19 | - Only big areas of data (blocks) can be erased 20 | - An erase will reset all bits in block to ones 21 | - Writing pulls one to zeroes 22 | - Zeroes can only be pulled to ones by erase 23 | - Wear leveling 24 | 25 | 26 | ## BUILDING 27 | 28 | `mkdir build; make` 29 | 30 | Otherwise, configure the `builddir` variable towards the top of `makefile` as something opposed to the default `build`. Sanity check on the host via `make test` and refer to `.travis.yml` for the official in-depth testing procedure. See the wiki for [integrating](https://github.com/pellepl/spiffs/wiki/Integrate-spiffs) spiffs into projects and [spiffsimg](https://github.com/nodemcu/nodemcu-firmware/tree/master/tools/spiffsimg) from [nodemcu](https://github.com/nodemcu) is a good example on the subject. 31 | 32 | 33 | ## FEATURES 34 | 35 | What spiffs does: 36 | - Specifically designed for low ram usage 37 | - Uses statically sized ram buffers, independent of number of files 38 | - Posix-like api: open, close, read, write, seek, stat, etc 39 | - It can run on any NOR flash, not only SPI flash - theoretically also on embedded flash of a microprocessor 40 | - Multiple spiffs configurations can run on same target - and even on same SPI flash device 41 | - Implements static wear leveling 42 | - Built in file system consistency checks 43 | - Highly configurable 44 | 45 | What spiffs does not: 46 | - Presently, spiffs does not support directories. It produces a flat structure. Creating a file with path *tmp/myfile.txt* will create a file called *tmp/myfile.txt* instead of a *myfile.txt* under directory *tmp*. 47 | - It is not a realtime stack. One write operation might last much longer than another. 48 | - Poor scalability. Spiffs is intended for small memory devices - the normal sizes for SPI flashes. Going beyond ~128Mbyte is probably a bad idea. This is a side effect of the design goal to use as little ram as possible. 49 | - Presently, it does not detect or handle bad blocks. 50 | - One configuration, one binary. There's no generic spiffs binary that handles all types of configurations. 51 | 52 | 53 | ## MORE INFO 54 | 55 | See the [wiki](https://github.com/pellepl/spiffs/wiki) for [configuring](https://github.com/pellepl/spiffs/wiki/Configure-spiffs), [integrating](https://github.com/pellepl/spiffs/wiki/Integrate-spiffs), [using](https://github.com/pellepl/spiffs/wiki/Using-spiffs), and [optimizing](https://github.com/pellepl/spiffs/wiki/Performance-and-Optimizing) spiffs. 56 | 57 | For design, see [docs/TECH_SPEC](https://github.com/pellepl/spiffs/blob/master/docs/TECH_SPEC). 58 | 59 | For a generic spi flash driver, see [this](https://github.com/pellepl/spiflash_driver). 60 | 61 | ## HISTORY 62 | 63 | ### 0.3.7 64 | - fixed prevent seeking to negative offsets #158 65 | - fixed file descriptor offsets not updated for multiple fds on same file #157 66 | - fixed cache page not closed for removed files #156 67 | - fixed a lseek bug when seeking exactly to end of a fully indexed first level LUT #148 68 | - fixed wear leveling issue #145 69 | - fixed attempt to write out of bounds in flash #130, 70 | - set file offset when seeking over end #121 (thanks @sensslen) 71 | - fixed seeking in virgin files #120 (thanks @sensslen) 72 | - Optional file metadata #128 (thanks @cesanta) 73 | - AFL testing framework #100 #143 (thanks @pjsg) 74 | - Testframe updates 75 | 76 | New API functions: 77 | - `SPIFFS_update_meta, SPIFFS_fupdate_meta` - updates metadata for a file 78 | 79 | New config defines: 80 | - `SPIFFS_OBJ_META_LEN` - enable possibility to add extra metadata to files 81 | 82 | ### 0.3.6 83 | - Fix range bug in index memory mapping #98 84 | - Add index memory mapping #97 85 | - Optimize SPIFFS_read for large files #96 86 | - Add temporal cache for opening files #95 87 | - More robust gc #93 (thanks @dismirlian) 88 | - Fixed a double write of same data in certain cache situations 89 | - Fixed an open bug in READ_ONLY builds 90 | - File not visible in SPIFFS_readdir #90 (thanks @benpicco-tmp) 91 | - Cache load code cleanup #92 (thanks @niclash) 92 | - Fixed lock/unlock asymmetry #88 #87 (thanks @JackJefferson, @dpruessner) 93 | - Testframe updates 94 | 95 | New API functions: 96 | - `SPIFFS_ix_map` - map index meta data to memory for a file 97 | - `SPIFFS_ix_unmap` - unmaps index meta data for a file 98 | - `SPIFFS_ix_remap` - changes file offset for index metadata map 99 | - `SPIFFS_bytes_to_ix_map_entries` - utility, get length of needed vector for given amount of bytes 100 | - `SPIFFS_ix_map_entries_to_bytes` - utility, get number of bytes a vector can represent given length 101 | 102 | New config defines: 103 | - `SPIFFS_IX_MAP` - enable possibility to map index meta data to memory for reading faster 104 | - `SPIFFS_TEMPORAL_FD_CACHE` - enable temporal cache for opening files faster 105 | - `SPIFFS_TEMPORAL_CACHE_HIT_SCORE` - for tuning the temporal cache 106 | 107 | ### 0.3.5 108 | - Fixed a bug in fs check 109 | - API returns actual error codes #84) (thanks @Nails) 110 | - Fix compiler warnings for non-gcc #83 #81 (thanks @Nails) 111 | - Unable to recover from full fs #82 (thanks @rojer) 112 | - Define SPIFFS_O_* flags #80 113 | - Problem with long filenames #79 (thanks @psjg) 114 | - Duplicate file name bug fix #74 (thanks @igrr) 115 | - SPIFFS_eof and SPIFFS_tell return wrong value #72 (thanks @ArtemPisarenko) 116 | - Bunch of testframe updates #77 #78 #86 (thanks @dpreussner, @psjg a.o) 117 | 118 | ### 0.3.4 119 | - Added user callback file func. 120 | - Fixed a stat bug with obj id. 121 | - SPIFFS_probe_fs added 122 | - Add possibility to compile a read-only version of spiffs 123 | - Make magic dependent on fs length, if needed (see #59 & #66) (thanks @hreintke) 124 | - Exposed SPIFFS_open_by_page_function 125 | - Zero-size file cannot be seek #57 (thanks @lishen2) 126 | - Add tell and eof functions #54 (thanks @raburton) 127 | - Make api string params const #53 (thanks @raburton) 128 | - Preserve user_data during mount() #51 (thanks @rojer) 129 | 130 | New API functions: 131 | - `SPIFFS_set_file_callback_func` - register a callback informing about file events 132 | - `SPIFFS_probe_fs` - probe a spi flash trying to figure out size of fs 133 | - `SPIFFS_open_by_page` - open a file by page index 134 | - `SPIFFS_eof` - checks if end of file is reached 135 | - `SPIFFS_tell` - returns current file offset 136 | 137 | New config defines: 138 | - `SPIFFS_READ_ONLY` 139 | - `SPIFFS_USE_MAGIC_LENGTH` 140 | 141 | ### 0.3.3 142 | **Might not be compatible with 0.3.2 structures. See issue #40** 143 | - Possibility to add integer offset to file handles 144 | - Truncate function presumes too few free pages #49 145 | - Bug in truncate function #48 (thanks @PawelDefee) 146 | - Update spiffs_gc.c - remove unnecessary parameter (thanks @PawelDefee) 147 | - Update INTEGRATION docs (thanks @PawelDefee) 148 | - Fix pointer truncation in 64-bit platforms (thanks @igrr) 149 | - Zero-sized files cannot be read #44 (thanks @rojer) 150 | - (More) correct calculation of max_id in obj_lu_find #42 #41 (thanks @lishen2) 151 | - Check correct error code in obj_lu_find_free #41 (thanks @lishen2) 152 | - Moar comments for SPIFFS_lseek (thanks @igrr) 153 | - Fixed padding in spiffs_page_object_ix #40 (thanks @jmattsson @lishen2) 154 | - Fixed gc_quick test (thanks @jmattsson) 155 | - Add SPIFFS_EXCL flag #36 156 | - SPIFFS_close may fail silently if cache is enabled #37 157 | - User data in callbacks #34 158 | - Ignoring SINGLETON build in cache setup (thanks Luca) 159 | - Compilation error fixed #32 (thanks @chotasanjiv) 160 | - Align cand_scores (thanks @hefloryd) 161 | - Fix build warnings when SPIFFS_CACHE is 0 (thanks @ajaybhargav) 162 | 163 | New config defines: 164 | - `SPIFFS_FILEHDL_OFFSET` 165 | 166 | ### 0.3.2 167 | - Limit cache size if too much cache is given (thanks pgeiem) 168 | - New feature - Controlled erase. #23 169 | - SPIFFS_rename leaks file descriptors #28 (thanks benpicco) 170 | - moved dbg print defines in test framework to params_test.h 171 | - lseek should return the resulting offset (thanks hefloryd) 172 | - fixed type on dbg ifdefs 173 | - silence warning about signed/unsigned comparison when spiffs_obj_id is 32 bit (thanks benpicco) 174 | - Possible error in test_spiffs.c #21 (thanks yihcdaso-yeskela) 175 | - Cache might writethrough too often #16 176 | - even moar testrunner updates 177 | - Test framework update and some added tests 178 | - Some thoughts for next gen 179 | - Test sigsevs when having too many sectors #13 (thanks alonewolfx2) 180 | - GC might be suboptimal #11 181 | - Fix eternal readdir when objheader at last block, last entry 182 | 183 | New API functions: 184 | - `SPIFFS_gc_quick` - call a nonintrusive gc 185 | - `SPIFFS_gc` - call a full-scale intrusive gc 186 | 187 | ### 0.3.1 188 | - Removed two return warnings, was too triggerhappy on release 189 | 190 | ### 0.3.0 191 | - Added existing namecheck when creating files 192 | - Lots of static analysis bugs #6 193 | - Added rename func 194 | - Fix SPIFFS_read length when reading beyond file size 195 | - Added reading beyond file length testcase 196 | - Made build a bit more configurable 197 | - Changed name in spiffs from "errno" to "err_code" due to conflicts compiling in mingw 198 | - Improved GC checks, fixed an append bug, more robust truncate for very special case 199 | - GC checks preempts GC, truncate even less picky 200 | - Struct alignment needed for some targets, define in spiffs config #10 201 | - Spiffs filesystem magic, definable in config 202 | 203 | New config defines: 204 | - `SPIFFS_USE_MAGIC` - enable or disable magic check upon mount 205 | - `SPIFFS_ALIGNED_OBJECT_INDEX_TABLES` - alignment for certain targets 206 | 207 | New API functions: 208 | - `SPIFFS_rename` - rename files 209 | - `SPIFFS_clearerr` - clears last errno 210 | - `SPIFFS_info` - returns info on used and total bytes in fs 211 | - `SPIFFS_format` - formats the filesystem 212 | - `SPIFFS_mounted` - checks if filesystem is mounted 213 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/afltests/100: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loboris/ESP32_spiffs_example/fc883eab6cec212c6de21c488cee4285fbb32a4c/components/spiffs/spiffs/afltests/100 -------------------------------------------------------------------------------- /components/spiffs/spiffs/afltests/200: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loboris/ESP32_spiffs_example/fc883eab6cec212c6de21c488cee4285fbb32a4c/components/spiffs/spiffs/afltests/200 -------------------------------------------------------------------------------- /components/spiffs/spiffs/afltests/a: -------------------------------------------------------------------------------- 1 | b55 2 | O4W4R4C4D4 3 | b45 4 | d5rh 5 | O4W4R4f4C4 6 | baaU 7 | d5rh 8 | OaWaRafaCa 9 | cd5rh 10 | OaWaRafaCa 11 | O4S4W4R4C4 12 | d5rh 13 | O4W4S4R4C4 14 | d5rh 15 | O4W4R4S4C4 16 | d5rh 17 | O4W4R4C4 18 | d5rh 19 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/afltests/b: -------------------------------------------------------------------------------- 1 | b55 2 | O4 3 | W?W?W?W?W?f4 4 | WW:W;f4 5 | C4 6 | b45 7 | d5rh 8 | O4W?R4f4C4 9 | baa 10 | d5rh 11 | OaWaRafaCa 12 | d5rh 13 | OaWaRafaCa 14 | O4W?R4C4 15 | d5rh 16 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/docs/TODO: -------------------------------------------------------------------------------- 1 | * When mending lost pages, also see if they fit into length specified in object index header 2 | 3 | SPIFFS2 thoughts 4 | 5 | * Instead of exact object id:s in the object lookup tables, use a hash of span index and object id. 6 | Eg. object id xor:ed with bit-reversed span index. 7 | This should decrease number of actual pages that needs to be visited when looking thru the obj lut. 8 | 9 | * Logical number of each block. When moving stuff in a garbage collected page, the free 10 | page is assigned the same number as the garbage collected. Thus, object index pages do not have to 11 | be rewritten. 12 | 13 | * Steal one page, use as a bit parity page. When starting an fs modification operation, write one bit 14 | as zero. When ending, write another bit as zero. On mount, if number of zeroes in page is uneven, a 15 | check is automatically run. -------------------------------------------------------------------------------- /components/spiffs/spiffs/files.mk: -------------------------------------------------------------------------------- 1 | ifndef spiffs 2 | $(warn defaulting path to generic spiffs module, spiffs variable not set) 3 | spiffs = ../generic/spiffs 4 | endif 5 | FLAGS += -DCONFIG_BUILD_SPIFFS 6 | INC += -I${spiffs}/src 7 | CPATH += ${spiffs}/src 8 | CFILES += spiffs_nucleus.c 9 | CFILES += spiffs_gc.c 10 | CFILES += spiffs_hydrogen.c 11 | CFILES += spiffs_cache.c 12 | CFILES += spiffs_check.c 13 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/makefile: -------------------------------------------------------------------------------- 1 | BINARY = linux_spiffs_test 2 | 3 | ############ 4 | # 5 | # Paths 6 | # 7 | ############ 8 | 9 | sourcedir = src 10 | builddir = build 11 | 12 | 13 | ############# 14 | # 15 | # Build tools 16 | # 17 | ############# 18 | 19 | CC ?= gcc 20 | LD ?= ld 21 | GDB ?= gdb 22 | OBJCOPY ?= objcopy 23 | OBJDUMP ?= objdump 24 | MKDIR ?= mkdir -p 25 | 26 | ############### 27 | # 28 | # Files and libs 29 | # 30 | ############### 31 | 32 | NO_TEST ?= 0 33 | CFLAGS = $(FLAGS) 34 | ifeq (1, $(strip $(NO_TEST))) 35 | CFILES_TEST = main.c 36 | CFLAGS += -DNO_TEST -Werror 37 | else 38 | CFILES_TEST = main.c \ 39 | test_spiffs.c \ 40 | test_dev.c \ 41 | test_check.c \ 42 | test_hydrogen.c \ 43 | test_bugreports.c \ 44 | testsuites.c \ 45 | testrunner.c 46 | CFLAGS += -D_SPIFFS_TEST 47 | endif 48 | include files.mk 49 | INCLUDE_DIRECTIVES = -I./${sourcedir} -I./${sourcedir}/default -I./${sourcedir}/test 50 | COMPILEROPTIONS = $(INCLUDE_DIRECTIVES) 51 | 52 | COMPILEROPTIONS_APP = $(INCLUDE_DIRECTIVES) \ 53 | -Wall -Wno-format-y2k -W -Wstrict-prototypes -Wmissing-prototypes \ 54 | -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch \ 55 | -Wshadow -Wcast-align -Wchar-subscripts -Winline -Wnested-externs\ 56 | -Wredundant-decls 57 | 58 | ############ 59 | # 60 | # Tasks 61 | # 62 | ############ 63 | 64 | vpath %.c ${sourcedir} ${sourcedir}/default ${sourcedir}/test 65 | 66 | OBJFILES = $(CFILES:%.c=${builddir}/%.o) 67 | OBJFILES_TEST = $(CFILES_TEST:%.c=${builddir}/%.o) 68 | 69 | DEPFILES = $(CFILES:%.c=${builddir}/%.d) $(CFILES_TEST:%.c=${builddir}/%.d) 70 | 71 | ALLOBJFILES += $(OBJFILES) $(OBJFILES_TEST) 72 | 73 | DEPENDENCIES = $(DEPFILES) 74 | 75 | # link object files, create binary 76 | $(BINARY): $(ALLOBJFILES) 77 | @echo "... linking" 78 | @${CC} $(LINKEROPTIONS) -o ${builddir}/$(BINARY) $(ALLOBJFILES) $(LIBS) 79 | ifeq (1, $(strip $(NO_TEST))) 80 | @echo "size: `du -b ${builddir}/${BINARY} | sed 's/\([0-9]*\).*/\1/g '` bytes" 81 | endif 82 | 83 | 84 | -include $(DEPENDENCIES) 85 | 86 | # compile c files 87 | $(OBJFILES) : ${builddir}/%.o:%.c 88 | @echo "... compile $@" 89 | @${CC} $(COMPILEROPTIONS_APP) $(CFLAGS) -g -c -o $@ $< 90 | 91 | $(OBJFILES_TEST) : ${builddir}/%.o:%.c 92 | @echo "... compile $@" 93 | @${CC} ${COMPILEROPTIONS} $(CFLAGS) -g -c -o $@ $< 94 | 95 | # make dependencies 96 | # @echo "... depend $@"; 97 | $(DEPFILES) : ${builddir}/%.d:%.c 98 | @rm -f $@; \ 99 | ${CC} $(COMPILEROPTIONS) -M $< > $@.$$$$; \ 100 | sed 's,\($*\)\.o[ :]*, ${builddir}/\1.o $@ : ,g' < $@.$$$$ > $@; \ 101 | rm -f $@.$$$$ 102 | 103 | all: mkdirs $(BINARY) 104 | 105 | mkdirs: 106 | -@${MKDIR} ${builddir} 107 | -@${MKDIR} test_data 108 | 109 | FILTER ?= 110 | 111 | test: $(BINARY) 112 | ifdef $(FILTER) 113 | ./build/$(BINARY) 114 | else 115 | ./build/$(BINARY) -f $(FILTER) 116 | endif 117 | 118 | test_failed: $(BINARY) 119 | ./build/$(BINARY) _tests_fail 120 | 121 | clean: 122 | @echo ... removing build files in ${builddir} 123 | @rm -f ${builddir}/*.o 124 | @rm -f ${builddir}/*.d 125 | @rm -f ${builddir}/*.elf 126 | 127 | ONOFF = 1 0 128 | OFFON = 0 1 129 | build-all: 130 | @for rdonly in $(ONOFF); do \ 131 | for singleton in $(ONOFF); do \ 132 | for hal_cb_xtra in $(OFFON); do \ 133 | for cache in $(OFFON); do \ 134 | for magic in $(OFFON); do \ 135 | for temporal_cache in $(OFFON); do \ 136 | for ix_map in $(OFFON); do \ 137 | echo; \ 138 | echo ============================================================; \ 139 | echo SPIFFS_READ_ONLY=$$rdonly; \ 140 | echo SPIFFS_SINGLETON=$$singleton; \ 141 | echo SPIFFS_HAL_CALLBACK_EXTRA=$$hal_cb_xtra; \ 142 | echo SPIFFS_CACHE, SPIFFS_CACHE_WR=$$cache; \ 143 | echo SPIFFS_USE_MAGIC, SPIFFS_USE_MAGIC_LENGTH=$$magic; \ 144 | echo SPIFFS_TEMPORAL_FD_CACHE=$$temporal_cache; \ 145 | echo SPIFFS_IX_MAP=$$ix_map; \ 146 | $(MAKE) clean && $(MAKE) FLAGS="\ 147 | -DSPIFFS_HAL_CALLBACK_EXTRA=$$hal_cb_xtra \ 148 | -DSPIFFS_SINGLETON=$$singleton \ 149 | -DSPIFFS_CACHE=$$cache \ 150 | -DSPIFFS_CACHE_WR=$$cache \ 151 | -DSPIFFS_READ_ONLY=$$rdonly \ 152 | -DSPIFFS_USE_MAGIC=$$magic \ 153 | -DSPIFFS_USE_MAGIC_LENGTH=$$magic \ 154 | -DSPIFFS_TEMPORAL_FD_CACHE=$$temporal_cache \ 155 | -DSPIFFS_IX_MAP=$$ix_map \ 156 | " NO_TEST=1; \ 157 | done || exit 1; \ 158 | done \ 159 | done \ 160 | done \ 161 | done \ 162 | done \ 163 | done 164 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/src/test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef NO_TEST 4 | #include "testrunner.h" 5 | #endif 6 | 7 | int main(int argc, char **args) { 8 | #ifndef NO_TEST 9 | run_tests(argc, args); 10 | #endif 11 | exit(EXIT_SUCCESS); 12 | } 13 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/src/test/params_test.h: -------------------------------------------------------------------------------- 1 | /* 2 | * params_test.h 3 | * 4 | * Created on: May 26, 2013 5 | * Author: petera 6 | */ 7 | 8 | #ifndef PARAMS_TEST_H_ 9 | #define PARAMS_TEST_H_ 10 | 11 | //////////////// TEST PARAMS //////////////// 12 | 13 | // default test total emulated spi flash size 14 | #define PHYS_FLASH_SIZE (16*1024*1024) 15 | // default test spiffs file system size 16 | #define SPIFFS_FLASH_SIZE (2*1024*1024) 17 | // default test spiffs file system offset in emulated spi flash 18 | #define SPIFFS_PHYS_ADDR (4*1024*1024) 19 | // default test sector size 20 | #define SECTOR_SIZE 65536 21 | // default test logical block size 22 | #define LOG_BLOCK (SECTOR_SIZE*2) 23 | // default test logical page size 24 | #define LOG_PAGE (SECTOR_SIZE/256) 25 | // default test number of filedescs 26 | #define DEFAULT_NUM_FD 16 27 | // default test number of cache pages 28 | #define DEFAULT_NUM_CACHE_PAGES 8 29 | 30 | // When testing, test bench create reference files for comparison on 31 | // the actual hard drive. By default, put these on ram drive for speed. 32 | #define TEST_PATH "/dev/shm/spiffs/test-data/" 33 | 34 | #define ASSERT(c, m) real_assert((c),(m), __FILE__, __LINE__); 35 | void real_assert(int c, const char *n, const char *file, int l); 36 | 37 | /////////// SPIFFS BUILD CONFIG //////////// 38 | 39 | // test using filesystem magic 40 | #ifndef SPIFFS_USE_MAGIC 41 | #define SPIFFS_USE_MAGIC 1 42 | #endif 43 | // test using filesystem magic length 44 | #ifndef SPIFFS_USE_MAGIC_LENGTH 45 | #define SPIFFS_USE_MAGIC_LENGTH 1 46 | #endif 47 | // test using extra param in callback 48 | #ifndef SPIFFS_HAL_CALLBACK_EXTRA 49 | #define SPIFFS_HAL_CALLBACK_EXTRA 1 50 | #endif 51 | // test using filehandle offset 52 | #ifndef SPIFFS_FILEHDL_OFFSET 53 | #define SPIFFS_FILEHDL_OFFSET 1 54 | // use this offset 55 | #define TEST_SPIFFS_FILEHDL_OFFSET 0x1000 56 | #endif 57 | 58 | #ifdef NO_TEST 59 | #define SPIFFS_LOCK(fs) 60 | #define SPIFFS_UNLOCK(fs) 61 | #else 62 | struct spiffs_t; 63 | extern void test_lock(struct spiffs_t *fs); 64 | extern void test_unlock(struct spiffs_t *fs); 65 | #define SPIFFS_LOCK(fs) test_lock(fs) 66 | #define SPIFFS_UNLOCK(fs) test_unlock(fs) 67 | #endif 68 | 69 | // dbg output 70 | #define SPIFFS_DBG(_f, ...) //printf("\x1b[32m" _f "\x1b[0m", ## __VA_ARGS__) 71 | #define SPIFFS_API_DBG(_f, ...) //printf("\n\x1b[1m\x1b[7m" _f "\x1b[0m", ## __VA_ARGS__) 72 | #define SPIFFS_GC_DBG(_f, ...) //printf("\x1b[36m" _f "\x1b[0m", ## __VA_ARGS__) 73 | #define SPIFFS_CACHE_DBG(_f, ...) //printf("\x1b[33m" _f "\x1b[0m", ## __VA_ARGS__) 74 | #define SPIFFS_CHECK_DBG(_f, ...) //printf("\x1b[31m" _f "\x1b[0m", ## __VA_ARGS__) 75 | 76 | // needed types 77 | typedef signed int s32_t; 78 | typedef unsigned int u32_t; 79 | typedef signed short s16_t; 80 | typedef unsigned short u16_t; 81 | typedef signed char s8_t; 82 | typedef unsigned char u8_t; 83 | 84 | #endif /* PARAMS_TEST_H_ */ 85 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/src/test/test_dev.c: -------------------------------------------------------------------------------- 1 | /* 2 | * test_dev.c 3 | * 4 | * Created on: Jul 14, 2013 5 | * Author: petera 6 | */ 7 | 8 | 9 | #include "testrunner.h" 10 | #include "test_spiffs.h" 11 | #include "spiffs_nucleus.h" 12 | #include "spiffs.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | SUITE(dev_tests) 21 | static void setup() { 22 | _setup(); 23 | } 24 | static void teardown() { 25 | _teardown(); 26 | } 27 | 28 | TEST(interrupted_write) { 29 | char *name = "interrupt"; 30 | char *name2 = "interrupt2"; 31 | int res; 32 | spiffs_file fd; 33 | 34 | const u32_t sz = SPIFFS_CFG_LOG_PAGE_SZ(FS)*8; 35 | u8_t *buf = malloc(sz); 36 | memrand(buf, sz); 37 | 38 | printf(" create reference file\n"); 39 | fd = SPIFFS_open(FS, name, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); 40 | TEST_CHECK(fd > 0); 41 | clear_flash_ops_log(); 42 | res = SPIFFS_write(FS, fd, buf, sz); 43 | TEST_CHECK(res >= 0); 44 | SPIFFS_close(FS, fd); 45 | 46 | u32_t written = get_flash_ops_log_write_bytes(); 47 | printf(" written bytes: %i\n", written); 48 | 49 | 50 | printf(" create error file\n"); 51 | fd = SPIFFS_open(FS, name2, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); 52 | TEST_CHECK(fd > 0); 53 | clear_flash_ops_log(); 54 | invoke_error_after_write_bytes(written/2, 0); 55 | res = SPIFFS_write(FS, fd, buf, sz); 56 | SPIFFS_close(FS, fd); 57 | TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_TEST); 58 | 59 | clear_flash_ops_log(); 60 | 61 | #if SPIFFS_CACHE 62 | // delete all cache 63 | spiffs_cache *cache = spiffs_get_cache(FS); 64 | cache->cpage_use_map = 0; 65 | #endif 66 | 67 | 68 | printf(" read error file\n"); 69 | fd = SPIFFS_open(FS, name2, SPIFFS_RDONLY, 0); 70 | TEST_CHECK(fd > 0); 71 | 72 | spiffs_stat s; 73 | res = SPIFFS_fstat(FS, fd, &s); 74 | TEST_CHECK(res >= 0); 75 | printf(" file size: %i\n", s.size); 76 | 77 | if (s.size > 0) { 78 | u8_t *buf2 = malloc(s.size); 79 | res = SPIFFS_read(FS, fd, buf2, s.size); 80 | TEST_CHECK(res >= 0); 81 | 82 | u32_t ix = 0; 83 | for (ix = 0; ix < s.size; ix += 16) { 84 | int i; 85 | printf(" "); 86 | for (i = 0; i < 16; i++) { 87 | printf("%02x", buf[ix+i]); 88 | } 89 | printf(" "); 90 | for (i = 0; i < 16; i++) { 91 | printf("%02x", buf2[ix+i]); 92 | } 93 | printf("\n"); 94 | } 95 | free(buf2); 96 | } 97 | SPIFFS_close(FS, fd); 98 | 99 | 100 | printf(" FS check\n"); 101 | SPIFFS_check(FS); 102 | 103 | printf(" read error file again\n"); 104 | fd = SPIFFS_open(FS, name2, SPIFFS_APPEND | SPIFFS_RDWR, 0); 105 | TEST_CHECK(fd > 0); 106 | res = SPIFFS_fstat(FS, fd, &s); 107 | TEST_CHECK(res >= 0); 108 | printf(" file size: %i\n", s.size); 109 | printf(" write file\n"); 110 | res = SPIFFS_write(FS, fd, buf, sz); 111 | TEST_CHECK(res >= 0); 112 | SPIFFS_close(FS, fd); 113 | 114 | free(buf); 115 | 116 | return TEST_RES_OK; 117 | 118 | } TEST_END 119 | 120 | SUITE_TESTS(dev_tests) 121 | ADD_TEST(interrupted_write) 122 | SUITE_END(dev_tests) 123 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/src/test/test_spiffs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * test_spiffs.h 3 | * 4 | * Created on: Jun 19, 2013 5 | * Author: petera 6 | */ 7 | 8 | #ifndef TEST_SPIFFS_H_ 9 | #define TEST_SPIFFS_H_ 10 | 11 | #include "spiffs.h" 12 | 13 | #define FS &__fs 14 | 15 | extern spiffs __fs; 16 | 17 | 18 | #define CHECK(r) if (!(r)) return -1; 19 | #define CHECK_RES(r) if (r < 0) return -1; 20 | #define FS_PURE_DATA_PAGES(fs) \ 21 | (SPIFFS_CFG_PHYS_SZ(fs) / SPIFFS_CFG_LOG_PAGE_SZ(fs)- (fs)->block_count * SPIFFS_OBJ_LOOKUP_PAGES(fs)) 22 | #define FS_PURE_DATA_SIZE(fs) \ 23 | FS_PURE_DATA_PAGES(fs) * SPIFFS_DATA_PAGE_SIZE(fs) 24 | 25 | typedef enum { 26 | EMPTY, 27 | SMALL, 28 | MEDIUM, 29 | LARGE, 30 | } tfile_size; 31 | 32 | typedef enum { 33 | UNTAMPERED, 34 | APPENDED, 35 | MODIFIED, 36 | REWRITTEN, 37 | } tfile_type; 38 | 39 | typedef enum { 40 | SHORT = 3, 41 | NORMAL = 15, 42 | LONG = 100, 43 | } tfile_life; 44 | 45 | typedef struct { 46 | tfile_size tsize; 47 | tfile_type ttype; 48 | tfile_life tlife; 49 | } tfile_conf; 50 | 51 | typedef struct { 52 | int state; 53 | spiffs_file fd; 54 | tfile_conf cfg; 55 | char name[32]; 56 | } tfile; 57 | 58 | void fs_reset(); 59 | void fs_reset_specific(u32_t addr_offset, u32_t phys_addr, u32_t phys_size, 60 | u32_t phys_sector_size, 61 | u32_t log_block_size, u32_t log_page_size); 62 | s32_t fs_mount_specific(u32_t phys_addr, u32_t phys_size, 63 | u32_t phys_sector_size, 64 | u32_t log_block_size, u32_t log_page_size); 65 | void fs_mount_dump(char *fname, 66 | u32_t addr_offset, u32_t phys_addr, u32_t phys_size, 67 | u32_t phys_sector_size, 68 | u32_t log_block_size, u32_t log_page_size); 69 | 70 | void fs_store_dump(char *fname); 71 | void fs_load_dump(char *fname); 72 | 73 | void fs_set_addr_offset(u32_t offset); 74 | int read_and_verify(char *name); 75 | int read_and_verify_fd(spiffs_file fd, char *name); 76 | void dump_page(spiffs *fs, spiffs_page_ix p); 77 | void hexdump(u32_t addr, u32_t len); 78 | char *make_test_fname(const char *name); 79 | void clear_test_path(); 80 | void area_write(u32_t addr, u8_t *buf, u32_t size); 81 | void area_set(u32_t addr, u8_t d, u32_t size); 82 | void area_read(u32_t addr, u8_t *buf, u32_t size); 83 | void dump_erase_counts(spiffs *fs); 84 | void dump_flash_access_stats(); 85 | void set_flash_ops_log(int enable); 86 | void clear_flash_ops_log(); 87 | u32_t get_flash_ops_log_read_bytes(); 88 | u32_t get_flash_ops_log_write_bytes(); 89 | void invoke_error_after_read_bytes(u32_t b, char once_only); 90 | void invoke_error_after_write_bytes(u32_t b, char once_only); 91 | void fs_set_validate_flashing(int i); 92 | int get_error_count(); 93 | int count_taken_fds(spiffs *fs); 94 | 95 | void memrand(u8_t *b, int len); 96 | int test_create_file(char *name); 97 | int test_create_and_write_file(char *name, int size, int chunk_size); 98 | u32_t get_spiffs_file_crc_by_fd(spiffs_file fd); 99 | u32_t get_spiffs_file_crc(char *name); 100 | void _setup(); 101 | void _setup_test_only(); 102 | void _teardown(); 103 | u32_t tfile_get_size(tfile_size s); 104 | int run_file_config(int cfg_count, tfile_conf* cfgs, int max_runs, int max_concurrent_files, int dbg); 105 | 106 | void test_lock(spiffs *fs); 107 | void test_unlock(spiffs *fs); 108 | 109 | #endif /* TEST_SPIFFS_H_ */ 110 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/src/test/testrunner.c: -------------------------------------------------------------------------------- 1 | /* 2 | * testrunner.c 3 | * 4 | * Created on: Jun 18, 2013 5 | * Author: petera 6 | */ 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "testrunner.h" 20 | 21 | static struct { 22 | test *tests; 23 | test *_last_test; 24 | int test_count; 25 | void (*on_stop)(test *t); 26 | test_res *failed; 27 | test_res *failed_last; 28 | test_res *stopped; 29 | test_res *stopped_last; 30 | FILE *spec; 31 | char incl_filter[256]; 32 | char excl_filter[256]; 33 | } test_main; 34 | 35 | void test_init(void (*on_stop)(test *t)) { 36 | test_main.on_stop = on_stop; 37 | } 38 | 39 | static int abort_on_error = 0; 40 | static int error_count = 0; 41 | 42 | static char check_spec(char *name) { 43 | if (test_main.spec) { 44 | fseek(test_main.spec, 0, SEEK_SET); 45 | char *line = NULL; 46 | size_t sz; 47 | ssize_t read; 48 | while ((read = getline(&line, &sz, test_main.spec)) != -1) { 49 | if (strncmp(line, name, strlen(line)-1) == 0) { 50 | free(line); 51 | return 1; 52 | } 53 | } 54 | free(line); 55 | return 0; 56 | } else { 57 | return 1; 58 | } 59 | } 60 | 61 | static char check_incl_filter(char *name) { 62 | if (strlen(test_main.incl_filter)== 0) return 1; 63 | return strstr(name, test_main.incl_filter) == 0 ? 0 : 2; 64 | } 65 | 66 | static char check_excl_filter(char *name) { 67 | if (strlen(test_main.excl_filter)== 0) return 1; 68 | return strstr(name, test_main.excl_filter) == 0 ? 1 : 0; 69 | } 70 | 71 | void _add_test(test_f f, char *name, void (*setup)(test *t), void (*teardown)(test *t), int non_default) { 72 | if (f == 0) return; 73 | if (!check_spec(name)) return; 74 | if (check_incl_filter(name) <= non_default) return; 75 | if (!check_excl_filter(name)) return; 76 | DBGT("adding test %s\n", name); 77 | test *t = malloc(sizeof(test)); 78 | memset(t, 0, sizeof(test)); 79 | t->f = f; 80 | strcpy(t->name, name); 81 | t->setup = setup; 82 | t->teardown = teardown; 83 | if (test_main.tests == 0) { 84 | test_main.tests = t; 85 | } else { 86 | test_main._last_test->_next = t; 87 | } 88 | test_main._last_test = t; 89 | test_main.test_count++; 90 | } 91 | 92 | static void add_res(test *t, test_res **head, test_res **last) { 93 | test_res *tr = malloc(sizeof(test_res)); 94 | memset(tr,0,sizeof(test_res)); 95 | strcpy(tr->name, t->name); 96 | if (*head == 0) { 97 | *head = tr; 98 | } else { 99 | (*last)->_next = tr; 100 | } 101 | *last = tr; 102 | } 103 | 104 | static void dump_res(test_res **head) { 105 | test_res *tr = (*head); 106 | while (tr) { 107 | test_res *next_tr = tr->_next; 108 | printf(" %s\n", tr->name); 109 | free(tr); 110 | tr = next_tr; 111 | } 112 | } 113 | 114 | int get_error_count(void) { 115 | return error_count; 116 | } 117 | 118 | void inc_error_count(void) { 119 | error_count++; 120 | } 121 | 122 | int set_abort_on_error(int val) { 123 | int old_val = abort_on_error; 124 | abort_on_error = val; 125 | 126 | return old_val; 127 | } 128 | 129 | int get_abort_on_error(void) { 130 | return abort_on_error; 131 | } 132 | 133 | int run_tests(int argc, char **args) { 134 | memset(&test_main, 0, sizeof(test_main)); 135 | int arg; 136 | int incl_filter = 0; 137 | int excl_filter = 0; 138 | for (arg = 1; arg < argc; arg++) { 139 | if (strlen(args[arg]) == 0) continue; 140 | if (0 == strcmp("-f", args[arg])) { 141 | incl_filter = 1; 142 | continue; 143 | } 144 | if (0 == strcmp("-e", args[arg])) { 145 | excl_filter = 1; 146 | continue; 147 | } 148 | if (incl_filter) { 149 | strcpy(test_main.incl_filter, args[arg]); 150 | incl_filter = 0; 151 | } else if (excl_filter) { 152 | strcpy(test_main.excl_filter, args[arg]); 153 | excl_filter = 0; 154 | } else { 155 | printf("running tests from %s\n", args[arg]); 156 | FILE *fd = fopen(args[1], "r"); 157 | if (fd == NULL) { 158 | printf("%s not found\n", args[arg]); 159 | return -2; 160 | } 161 | test_main.spec = fd; 162 | } 163 | } 164 | 165 | DBGT("adding suites...\n"); 166 | add_suites(); 167 | DBGT("%i tests added\n", test_main.test_count); 168 | if (test_main.spec) { 169 | fclose(test_main.spec); 170 | } 171 | 172 | if (test_main.test_count == 0) { 173 | printf("No tests to run\n"); 174 | return 0; 175 | } 176 | 177 | int fd_success = open("_tests_ok", O_APPEND | O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); 178 | int fd_bad = open("_tests_fail", O_APPEND | O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); 179 | 180 | DBGT("running tests...\n"); 181 | int ok = 0; 182 | int failed = 0; 183 | int stopped = 0; 184 | test *cur_t = test_main.tests; 185 | int i = 1; 186 | while (cur_t) { 187 | cur_t->setup(cur_t); 188 | test *next_test = cur_t->_next; 189 | DBGT("TEST %i/%i : running test %s\n", i, test_main.test_count, cur_t->name); 190 | i++; 191 | int start_error_count = get_error_count(); 192 | int res = cur_t->f(cur_t); 193 | if (res == TEST_RES_OK && get_error_count() != start_error_count) { 194 | res = TEST_RES_FAIL; 195 | } 196 | cur_t->test_result = res; 197 | int fd = res == TEST_RES_OK ? fd_success : fd_bad; 198 | write(fd, cur_t->name, strlen(cur_t->name)); 199 | write(fd, "\n", 1); 200 | switch (res) { 201 | case TEST_RES_OK: 202 | ok++; 203 | printf(" .. ok\n"); 204 | break; 205 | case TEST_RES_FAIL: 206 | failed++; 207 | printf(" .. FAILED\n"); 208 | if (test_main.on_stop) test_main.on_stop(cur_t); 209 | add_res(cur_t, &test_main.failed, &test_main.failed_last); 210 | break; 211 | case TEST_RES_ASSERT: 212 | stopped++; 213 | printf(" .. ABORTED\n"); 214 | if (test_main.on_stop) test_main.on_stop(cur_t); 215 | add_res(cur_t, &test_main.stopped, &test_main.stopped_last); 216 | break; 217 | } 218 | cur_t->teardown(cur_t); 219 | free(cur_t); 220 | cur_t = next_test; 221 | } 222 | close(fd_success); 223 | close(fd_bad); 224 | DBGT("ran %i tests\n", test_main.test_count); 225 | printf("Test report, %i tests\n", test_main.test_count); 226 | printf("%i succeeded\n", ok); 227 | printf("%i failed\n", failed); 228 | dump_res(&test_main.failed); 229 | printf("%i stopped\n", stopped); 230 | dump_res(&test_main.stopped); 231 | if (ok < test_main.test_count) { 232 | printf("\nFAILED\n"); 233 | return -1; 234 | } else { 235 | printf("\nALL TESTS OK\n"); 236 | return 0; 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/src/test/testrunner.h: -------------------------------------------------------------------------------- 1 | /* 2 | * testrunner.h 3 | * 4 | * Created on: Jun 19, 2013 5 | * Author: petera 6 | */ 7 | 8 | /* 9 | 10 | file mysuite.c: 11 | 12 | SUITE(mysuite) 13 | 14 | static void setup(test *t) {} 15 | 16 | static void teardown(test *t) {} 17 | 18 | TEST(mytest) { 19 | printf("mytest runs now..\n"); 20 | return 0; 21 | } TEST_END 22 | 23 | SUITE_TESTS(mysuite) 24 | ADD_TEST(mytest) 25 | SUITE_END(mysuite) 26 | 27 | 28 | 29 | file mysuite2.c: 30 | 31 | SUITE(mysuite2) 32 | 33 | static void setup(test *t) {} 34 | 35 | static void teardown(test *t) {} 36 | 37 | TEST(mytest2a) { 38 | printf("mytest2a runs now..\n"); 39 | return 0; 40 | } TEST_END 41 | 42 | TEST(mytest2b) { 43 | printf("mytest2b runs now..\n"); 44 | return 0; 45 | } TEST_END 46 | 47 | SUITE_TESTS(mysuite2) 48 | ADD_TEST(mytest2a) 49 | ADD_TEST(mytest2b) 50 | SUITE_END(mysuite2) 51 | 52 | 53 | some other file.c: 54 | 55 | void add_suites() { 56 | ADD_SUITE(mysuite); 57 | ADD_SUITE(mysuite2); 58 | } 59 | */ 60 | 61 | #ifndef TESTRUNNER_H_ 62 | #define TESTRUNNER_H_ 63 | 64 | #define TEST_RES_OK 0 65 | #define TEST_RES_FAIL -1 66 | #define TEST_RES_ASSERT -2 67 | 68 | #define ERREXIT() if (get_abort_on_error()) abort(); else inc_error_count() 69 | 70 | struct test_s; 71 | 72 | typedef int (*test_f)(struct test_s *t); 73 | 74 | typedef struct test_s { 75 | test_f f; 76 | char name[256]; 77 | void *data; 78 | void (*setup)(struct test_s *t); 79 | void (*teardown)(struct test_s *t); 80 | struct test_s *_next; 81 | unsigned char test_result; 82 | } test; 83 | 84 | typedef struct test_res_s { 85 | char name[256]; 86 | struct test_res_s *_next; 87 | } test_res; 88 | 89 | #define TEST_CHECK(x) if (!(x)) { \ 90 | printf(" TEST FAIL %s:%d\n", __FILE__, __LINE__); \ 91 | goto __fail_stop; \ 92 | } 93 | #define TEST_CHECK_EQ(x, y) if ((x) != (y)) { \ 94 | printf(" TEST FAIL %s:%d, %d != %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ 95 | goto __fail_stop; \ 96 | } 97 | #define TEST_CHECK_NEQ(x, y) if ((x) == (y)) { \ 98 | printf(" TEST FAIL %s:%d, %d == %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ 99 | goto __fail_stop; \ 100 | } 101 | #define TEST_CHECK_GT(x, y) if ((x) <= (y)) { \ 102 | printf(" TEST FAIL %s:%d, %d <= %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ 103 | goto __fail_stop; \ 104 | } 105 | #define TEST_CHECK_LT(x, y) if ((x) >= (y)) { \ 106 | printf(" TEST FAIL %s:%d, %d >= %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ 107 | goto __fail_stop; \ 108 | } 109 | #define TEST_CHECK_GE(x, y) if ((x) < (y)) { \ 110 | printf(" TEST FAIL %s:%d, %d < %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ 111 | goto __fail_stop; \ 112 | } 113 | #define TEST_CHECK_LE(x, y) if ((x) > (y)) { \ 114 | printf(" TEST FAIL %s:%d, %d > %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ 115 | goto __fail_stop; \ 116 | } 117 | #define TEST_ASSERT(x) if (!(x)) { \ 118 | printf(" TEST ASSERT %s:%d\n", __FILE__, __LINE__); \ 119 | goto __fail_assert; \ 120 | } 121 | 122 | #define DBGT(...) printf(__VA_ARGS__) 123 | 124 | #define str(s) #s 125 | 126 | #define SUITE(sui) 127 | 128 | #define SUITE_TESTS(sui) \ 129 | void _add_suite_tests_##sui(void) { 130 | 131 | #define SUITE_END(sui) \ 132 | } 133 | 134 | #define ADD_TEST(tf) \ 135 | _add_test(__test_##tf, str(tf), setup, teardown, 0); 136 | 137 | #define ADD_TEST_NON_DEFAULT(tf) \ 138 | _add_test(__test_##tf, str(tf), setup, teardown, 1); 139 | 140 | #define ADD_SUITE(sui) \ 141 | extern void _add_suite_tests_##sui(void); \ 142 | _add_suite_tests_##sui(); 143 | 144 | #define TEST(tf) \ 145 | static int __test_##tf(struct test_s *t) { do 146 | 147 | #define TEST_END \ 148 | while(0); \ 149 | __fail_stop: return TEST_RES_FAIL; \ 150 | __fail_assert: return TEST_RES_ASSERT; \ 151 | } 152 | 153 | int set_abort_on_error(int val); 154 | int get_abort_on_error(void); 155 | int get_error_count(void); 156 | void inc_error_count(void); 157 | 158 | void add_suites(void); 159 | void test_init(void (*on_stop)(test *t)); 160 | // returns 0 if all tests ok, -1 if any test failed, -2 on badness 161 | int run_tests(int argc, char **args); 162 | void _add_suite(const char *suite_name); 163 | void _add_test(test_f f, char *name, void (*setup)(test *t), void (*teardown)(test *t), int non_default); 164 | 165 | #endif /* TESTRUNNER_H_ */ 166 | -------------------------------------------------------------------------------- /components/spiffs/spiffs/src/test/testsuites.c: -------------------------------------------------------------------------------- 1 | /* 2 | * testsuites.c 3 | * 4 | * Created on: Jun 19, 2013 5 | * Author: petera 6 | */ 7 | 8 | #include "testrunner.h" 9 | 10 | void add_suites(void) { 11 | //ADD_SUITE(dev_tests); 12 | ADD_SUITE(check_tests); 13 | ADD_SUITE(hydrogen_tests); 14 | ADD_SUITE(bug_tests); 15 | } 16 | -------------------------------------------------------------------------------- /components/spiffs/test/component.mk: -------------------------------------------------------------------------------- 1 | COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive 2 | -------------------------------------------------------------------------------- /components/spiffs_image/Makefile.projbuild: -------------------------------------------------------------------------------- 1 | 2 | SPIFFS_IMAGE_COMPONENT_PATH := $(COMPONENT_PATH) 3 | ifeq ($(OS),Windows_NT) 4 | MKSPIFFS_BIN="mkspiffs.exe" 5 | MKSPIFFS_BIN_PATH := $(PROJECT_PATH)/components/mkspiffs/mkspiffs.exe 6 | else 7 | MKSPIFFS_BIN="mkspiffs" 8 | MKSPIFFS_BIN_PATH := $(PROJECT_PATH)/components/mkspiffs/mkspiffs 9 | endif 10 | 11 | $(shell $(SPIFFS_IMAGE_COMPONENT_PATH)/spiffs_part_info.py) 12 | 13 | include $(SPIFFS_IMAGE_COMPONENT_PATH)/spiffs_param.mk 14 | 15 | .PHONY: flashfs 16 | .PHONY: makefs 17 | .PHONY: copyfs 18 | 19 | flashfs: 20 | @echo "Make & flash spiffs image ..." 21 | $(MKSPIFFS_BIN_PATH) -c $(SPIFFS_IMAGE_COMPONENT_PATH)/image -b 4096 -p 256 -s $(PART_SPIFFS_SIZE) $(BUILD_DIR_BASE)/spiffs_image.img 22 | $(ESPTOOLPY_WRITE_FLASH) $(PART_SPIFFS_BASE_ADDR) $(BUILD_DIR_BASE)/spiffs_image.img 23 | 24 | makefs: 25 | @echo "Making spiffs image ..." 26 | $(MKSPIFFS_BIN_PATH) -c $(SPIFFS_IMAGE_COMPONENT_PATH)/image -b 4096 -p 256 -s $(PART_SPIFFS_SIZE) $(BUILD_DIR_BASE)/spiffs_image.img 27 | 28 | copyfs: 29 | @echo "Flashing spiffs image ..." 30 | $(ESPTOOLPY_WRITE_FLASH) $(PART_SPIFFS_BASE_ADDR) $(SPIFFS_IMAGE_COMPONENT_PATH)/spiffs_image.img 31 | -------------------------------------------------------------------------------- /components/spiffs_image/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Component Makefile 3 | # 4 | 5 | COMPONENT_SRCDIRS := 6 | COMPONENT_ADD_INCLUDEDIRS := 7 | -------------------------------------------------------------------------------- /components/spiffs_image/image/images/test/test3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loboris/ESP32_spiffs_example/fc883eab6cec212c6de21c488cee4285fbb32a4c/components/spiffs_image/image/images/test/test3.jpg -------------------------------------------------------------------------------- /components/spiffs_image/image/images/test1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loboris/ESP32_spiffs_example/fc883eab6cec212c6de21c488cee4285fbb32a4c/components/spiffs_image/image/images/test1.jpg -------------------------------------------------------------------------------- /components/spiffs_image/image/images/test2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loboris/ESP32_spiffs_example/fc883eab6cec212c6de21c488cee4285fbb32a4c/components/spiffs_image/image/images/test2.jpg -------------------------------------------------------------------------------- /components/spiffs_image/image/images/test4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loboris/ESP32_spiffs_example/fc883eab6cec212c6de21c488cee4285fbb32a4c/components/spiffs_image/image/images/test4.jpg -------------------------------------------------------------------------------- /components/spiffs_image/image/spiffs.info: -------------------------------------------------------------------------------- 1 | INTRODUCTION 2 | 3 | Spiffs is a file system intended for SPI NOR flash devices on embedded targets. 4 | Spiffs is designed with following characteristics in mind: 5 | 6 | * Small (embedded) targets, sparse RAM without heap 7 | * Only big areas of data (blocks) can be erased 8 | * An erase will reset all bits in block to ones 9 | * Writing pulls one to zeroes 10 | * Zeroes can only be pulled to ones by erase 11 | * Wear leveling 12 | -------------------------------------------------------------------------------- /components/spiffs_image/spiffs_image.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loboris/ESP32_spiffs_example/fc883eab6cec212c6de21c488cee4285fbb32a4c/components/spiffs_image/spiffs_image.img -------------------------------------------------------------------------------- /components/spiffs_image/spiffs_param.mk: -------------------------------------------------------------------------------- 1 | PART_SPIFFS_SIZE="1048576" 2 | PART_SPIFFS_BASE_ADDR="0x110000" 3 | -------------------------------------------------------------------------------- /components/spiffs_image/spiffs_part_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # ESP32 partition table generation tool 4 | # 5 | # Converts partition tables to/from CSV and binary formats. 6 | # 7 | # See http://esp-idf.readthedocs.io/en/latest/api-guides/partition-tables.html 8 | # for explanation of partition table structure and uses. 9 | # 10 | # Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 11 | # 12 | # Licensed under the Apache License, Version 2.0 (the "License"); 13 | # you may not use this file except in compliance with the License. 14 | # You may obtain a copy of the License at 15 | # 16 | # http:#www.apache.org/licenses/LICENSE-2.0 17 | # 18 | # Unless required by applicable law or agreed to in writing, software 19 | # distributed under the License is distributed on an "AS IS" BASIS, 20 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | # See the License for the specific language governing permissions and 22 | # limitations under the License. 23 | from __future__ import print_function, division 24 | import argparse 25 | import os 26 | import re 27 | import struct 28 | import sys 29 | 30 | MAX_PARTITION_LENGTH = 0xC00 # 3K for partition data (96 entries) leaves 1K in a 4K sector for signature 31 | 32 | __version__ = '1.0' 33 | 34 | quiet = False 35 | 36 | def status(msg): 37 | """ Print status message to stderr """ 38 | if not quiet: 39 | critical(msg) 40 | 41 | def critical(msg): 42 | """ Print critical message to stderr """ 43 | if not quiet: 44 | sys.stderr.write(msg) 45 | sys.stderr.write('\n') 46 | 47 | class PartitionTable(list): 48 | def __init__(self): 49 | super(PartitionTable, self).__init__(self) 50 | 51 | @classmethod 52 | def from_csv(cls, csv_contents): 53 | res = PartitionTable() 54 | lines = csv_contents.splitlines() 55 | 56 | def expand_vars(f): 57 | f = os.path.expandvars(f) 58 | m = re.match(r'(? 0: 183 | raise InputError("CSV flag column contains unknown flag '%s'" % (flag)) 184 | 185 | return res 186 | 187 | def __eq__(self, other): 188 | return self.name == other.name and self.type == other.type \ 189 | and self.subtype == other.subtype and self.offset == other.offset \ 190 | and self.size == other.size 191 | 192 | def __repr__(self): 193 | def maybe_hex(x): 194 | return "0x%x" % x if x is not None else "None" 195 | return "PartitionDefinition('%s', 0x%x, 0x%x, %s, %s)" % (self.name, self.type, self.subtype or 0, 196 | maybe_hex(self.offset), maybe_hex(self.size)) 197 | 198 | def __str__(self): 199 | return "Part '%s' %d/%d @ 0x%x size 0x%x" % (self.name, self.type, self.subtype, self.offset or -1, self.size or -1) 200 | 201 | def __cmp__(self, other): 202 | return self.offset - other.offset 203 | 204 | def parse_type(self, strval): 205 | if strval == "": 206 | raise InputError("Field 'type' can't be left empty.") 207 | return parse_int(strval, self.TYPES) 208 | 209 | def parse_subtype(self, strval): 210 | if strval == "": 211 | return 0 # default 212 | return parse_int(strval, self.SUBTYPES.get(self.type, {})) 213 | 214 | def parse_address(self, strval): 215 | if strval == "": 216 | return None # PartitionTable will fill in default 217 | return parse_int(strval) 218 | 219 | def verify(self): 220 | if self.type is None: 221 | raise ValidationError(self, "Type field is not set") 222 | if self.subtype is None: 223 | raise ValidationError(self, "Subtype field is not set") 224 | if self.offset is None: 225 | raise ValidationError(self, "Offset field is not set") 226 | align = self.ALIGNMENT.get(self.type, 4) 227 | if self.offset % align: 228 | raise ValidationError(self, "Offset 0x%x is not aligned to 0x%x" % (self.offset, align)) 229 | if self.size is None: 230 | raise ValidationError(self, "Size field is not set") 231 | 232 | STRUCT_FORMAT = "<2sBBLL16sL" 233 | 234 | 235 | def parse_int(v, keywords={}): 236 | """Generic parser for integer fields - int(x,0) with provision for 237 | k/m/K/M suffixes and 'keyword' value lookup. 238 | """ 239 | try: 240 | for letter, multiplier in [ ("k",1024), ("m",1024*1024) ]: 241 | if v.lower().endswith(letter): 242 | return parse_int(v[:-1], keywords) * multiplier 243 | return int(v, 0) 244 | except ValueError: 245 | if len(keywords) == 0: 246 | raise InputError("Invalid field value %s" % v) 247 | try: 248 | return keywords[v.lower()] 249 | except KeyError: 250 | raise InputError("Value '%s' is not valid. Known keywords: %s" % (v, ", ".join(keywords))) 251 | 252 | def main(): 253 | global quiet 254 | parser = argparse.ArgumentParser(description='ESP32 partition table utility') 255 | 256 | parser.add_argument('--verify', '-v', help='Verify partition table fields', default=True, action='store_false') 257 | parser.add_argument('--quiet', '-q', help="Don't print status messages to stderr", action='store_true') 258 | 259 | args = parser.parse_args() 260 | 261 | quiet = args.quiet 262 | try: 263 | os.remove('components/spiffs_image/spiffs_param.mk') 264 | except: 265 | pass 266 | f = open('partitions_example.csv', 'r') 267 | input = f.read() 268 | input = input.decode() 269 | #status("Parsing CSV input...") 270 | table = PartitionTable.from_csv(input) 271 | 272 | if args.verify: 273 | #status("Verifying table...") 274 | table.verify() 275 | 276 | lastpart = table[len(table)-1] 277 | if lastpart.name == 'storage': 278 | #print(lastpart.subtype, "0x%x" % lastpart.offset, lastpart.size) 279 | f = open('components/spiffs_image/spiffs_param.mk', 'w') 280 | f.write('PART_SPIFFS_SIZE="%d"\n' % lastpart.size) 281 | f.write('PART_SPIFFS_BASE_ADDR="0x%x"\n' % lastpart.offset) 282 | f.close 283 | 284 | 285 | class InputError(RuntimeError): 286 | def __init__(self, e): 287 | super(InputError, self).__init__(e) 288 | 289 | 290 | class ValidationError(InputError): 291 | def __init__(self, partition, message): 292 | super(ValidationError, self).__init__( 293 | "Partition %s invalid: %s" % (partition.name, message)) 294 | 295 | 296 | if __name__ == '__main__': 297 | try: 298 | main() 299 | except InputError as e: 300 | print(e, file=sys.stderr) 301 | sys.exit(2) 302 | -------------------------------------------------------------------------------- /main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "SPIffs Example Configuration" 2 | 3 | config EXAMPLE_RUN_MULTITASK_TEST 4 | bool "Run multitask test" 5 | default n 6 | help 7 | Run multitask test, 3 tasks are created. 8 | Each task will perform 1000 read&write operations. 9 | 10 | config EXAMPLE_USE_WIFI 11 | bool "Use wifi in this example" 12 | default n 13 | help 14 | If WiFi is used ntp server will be used to provide the exact time 15 | and file timestamps will be correct. 16 | 17 | config WIFI_SSID 18 | string "WiFi SSID" 19 | depends on EXAMPLE_USE_WIFI 20 | default "myssid" 21 | help 22 | SSID (network name) for the example to connect to. 23 | 24 | config WIFI_PASSWORD 25 | string "WiFi Password" 26 | depends on EXAMPLE_USE_WIFI 27 | default "mypassword" 28 | help 29 | WiFi password (WPA or WPA2) for the example to use. 30 | 31 | 32 | endmenu 33 | -------------------------------------------------------------------------------- /main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Main Makefile. This is basically the same as a component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | -------------------------------------------------------------------------------- /partitions_example.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild 3 | nvs, data, nvs, 0x9000, 0x6000, 4 | phy_init, data, phy, 0xf000, 0x1000, 5 | factory, app, factory, 0x10000, 1M, 6 | storage, data, spiffs, , 1M, 7 | -------------------------------------------------------------------------------- /sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | CONFIG_PARTITION_TABLE_CUSTOM=y 2 | CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv" 3 | CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 4 | CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv" 5 | CONFIG_APP_OFFSET=0x10000 6 | CONFIG_TCPIP_TASK_STACK_SIZE=4096 7 | CONFIG_ESP32_PANIC_PRINT_HALT=y 8 | CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y 9 | CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16 10 | CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 11 | CONFIG_FREERTOS_HZ=1000 12 | CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2 13 | CONFIG_LWIP_SO_REUSE=y 14 | CONFIG_TCPIP_TASK_STACK_SIZE=8192 15 | CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=8192 16 | CONFIG_ESPTOOLPY_AFTER_NORESET=y 17 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y 18 | CONFIG_MAIN_TASK_STACK_SIZE=16384 19 | CONFIG_TASK_WDT_TIMEOUT_S=30 20 | CONFIG_SPIFFS_META_LENGTH=4 21 | CONFIG_SPIFFS_USE_MTIME=y 22 | --------------------------------------------------------------------------------