diff --git a/.gitmodules b/.gitmodules index 44480bd897a..7036aadd4dc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,6 +10,9 @@ [submodule "libs/eurorack/eurorack"] path = libs/eurorack/eurorack url = https://github.com/surge-synthesizer/eurorack.git +[submodule "libs/filesystem/ghc-filesystem"] + path = libs/filesystem/ghc-filesystem + url = https://github.com/gulrak/filesystem.git [submodule "libs/oddsound-mts/MTS-ESP"] path = libs/oddsound-mts/MTS-ESP url = https://github.com/ODDSound/MTS-ESP @@ -29,12 +32,3 @@ path = libs/PEGTL url = https://github.com/taocpp/PEGTL.git branch = 2.x -[submodule "libs/sst/sst-plugininfra"] - path = libs/sst/sst-plugininfra - url = https://github.com/surge-synthesizer/sst-plugininfra -[submodule "libs/sst/sst-cpputils"] - path = libs/sst/sst-cpputils - url = https://github.com/surge-synthesizer/sst-cpputils -[submodule "libs/clap-juce-extensions"] - path = libs/clap-juce-extensions - url = https://github.com/free-audio/clap-juce-extensions diff --git a/CMakeLists.txt b/CMakeLists.txt index afb37c42e3d..7d6732b5fb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT BUILD_TESTING) option(BUILD_TESTING "" OFF) endif() -project(Surge VERSION 1.1.0 LANGUAGES C CXX ASM) +project(Surge VERSION 1.0.0 LANGUAGES C CXX ASM) # Banner {{{ message(STATUS "It's Surge XT, folks! Version is ${PROJECT_VERSION}") @@ -46,7 +46,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") # Any Clang or any GCC add_compile_options( -Wno-multichar - # Targeting Windows with GCC/Clang is experimental + # Targetting Windows with GCC/Clang is experimental $<$>:-Werror> # PE/COFF doesn't support visibility @@ -54,7 +54,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") # Inlines visibility is only relevant with C++ $<$>,$>:-fvisibility-inlines-hidden> - # BP note: If you want to turn on llvm/gcc sanitize undo this and the link options below + # BP note: If you want to turn on llvm/gcc santize undo this and the link options below # -fsanitize=address -fsanitize=undefined ) diff --git a/README.md b/README.md index 30a0ad00aaf..66b5a34f07e 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [from our website](https://surge-synthesizer.github.io). Surge Synth Team makes regular releases for all supported platforms.** -**Over 2021, after the successful release of Surge 1.9, the Surge Synth team undertook an effort to rebuild Surge in JUCE +**Over 2021, after the succesful release of Surge 1.9, the Surge Synth team undertook an effort to rebuild Surge in JUCE and add a variety of features. This project resulted in the new version of Surge, called 'Surge XT'. The head of this repo contains the current version of Surge XT. If you are looking to compile a stable production version of Surge, we tag each release, so if you want to compile Surge 1.9, please check out the `release_1.9.0` tag.** @@ -131,7 +131,7 @@ cmake -Bbuild -DBUILD_USING_MY_ASIO_LICENSE=True On Linux, using a community fork of JUCE, you can build an LV2. Here's how! We assume you have checked out Surge and can build. -First, clone https://github.com/lv2-porting-project/JUCE/tree/lv2 on branch lv2, to some directory of your choosing. +First, clone https://github.com/lv2-porting-project/JUCE/tree/lv2 on branch lv2, to some directory of your chosing. ``` sudo apt-get install -y lv2-dev diff --git a/doc/Developer Guide.md b/doc/Developer Guide.md index c8f4dbed0b9..8e5e024f39f 100644 --- a/doc/Developer Guide.md +++ b/doc/Developer Guide.md @@ -65,7 +65,7 @@ CI will fail (`linux-codequality` job). Make sure the diffs you submit for mergi * `class HaveCamelCaseNames` * `void functionsAreCamelCaseWithLowerFirst` * We are not using `s_` or `m_` or equivalent notations for members or statics -* Full namespaces are generally preferred over `using`. We are trying to use +* Full namespaces are generally prefered over `using`. We are trying to use `std::vector` over `vector` in the code. * Don't do `using namespace` in header files. Don't `using namespace std` in new code (but it is in some existing code). * Use namespaces, not classes to group functions. Check out how we implemented `UserInteractions.h` diff --git a/doc/Dynamic Names, Deactivation and Bipolarity.md b/doc/Dynamic Names, Deactivation and Bipolarity.md index 6988c42be92..8abab0bfdee 100644 --- a/doc/Dynamic Names, Deactivation and Bipolarity.md +++ b/doc/Dynamic Names, Deactivation and Bipolarity.md @@ -35,7 +35,7 @@ associated oscillator using control groups, use that to look up oscillator mode, understand your parameter index, and return the right name. Similarly, the `lfoPhaseName` handler which is set up for all LFOs in `SurgePatch.cpp` -creates a static handler and assigns it to all the `start_phase` dynamic +creates a static handler and assignes it to all the `start_phase` dynamic names to swap Phase and Shuffle text labels based on LFO type. ## Dynamic Activation @@ -63,7 +63,7 @@ or null if there is no parent. So basically, a good implementation of `getValue()` is to look up the parent param and return its decctivation status, and for `getPrimaryActivationDriver()` to look up the -parent parameter and return a pointer to it. LPG parameteres in EuroTwist do precisely this. +parent parameter and return a poitner to it. LPG parameteres in EuroTwist do precisely this. ### Follow Value Pattern diff --git a/doc/How to Git.md b/doc/How to Git.md index ac5acd43708..6cb427c64dc 100644 --- a/doc/How to Git.md +++ b/doc/How to Git.md @@ -159,7 +159,7 @@ pattern would be develop on Mac, do a commit, then test it on Windows and Linux. make a one-line change and commit that. Now your change, which is still "one thing", has two commits. Or perhaps, you develop your code over a week committing regularly and all those intermediate work commits -aren't ones you want to make visible. Or perhaps you develop, then format as a last step and have changes. +aren't ones you want to make visibile. Or perhaps you develop, then format as a last step and have changes. In any case, as maintainers, we would sooner have a small number of git commits in our pull requests. @@ -208,7 +208,7 @@ paul:~/dev/music/surge$ git cherry -v main ``` Now at this point you could push your branch (`git push origin update-git-howto`) and the PR would update -and would have two commits in it. Continuous integration would run its course and voila! But the maintainers would probably +and would have two commits in it. Continous integration would run its course and voila! But the maintainers would probably squash those commits and rewrite your commit message, so you may want to squash down to one commit. Here's how you do it. First rebase interactively with `git rebase -i main`. You will see an editor which looks like this: diff --git a/doc/Surge Architecture.md b/doc/Surge Architecture.md index 263453ce88a..08e1f3733b8 100644 --- a/doc/Surge Architecture.md +++ b/doc/Surge Architecture.md @@ -46,7 +46,7 @@ of the UI (like those delivered by the host) to be reflected in the UI. Surge voice allocation and voice stealing code is complicated, supporting multiple polyphony modes and MPE, which adds substantial complexity. The core data structure is a list of voices -which are allocated at startup and configured with an in-place constructor. Each has a reference +which are allocated at startup and configured with an in-place contructor. Each has a reference to state for the channel in which it is playing. The voice class is in `src/common/dsp/SurgeVoice.h` and contains a `SurgeVoiceState`. diff --git a/libs/clap-juce-extensions b/libs/clap-juce-extensions deleted file mode 160000 index 66ed912021c..00000000000 --- a/libs/clap-juce-extensions +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 66ed912021c1820911329d5aaa0392eaec87ee68 diff --git a/libs/filesystem/CMakeLists.txt b/libs/filesystem/CMakeLists.txt new file mode 100644 index 00000000000..95e932194c7 --- /dev/null +++ b/libs/filesystem/CMakeLists.txt @@ -0,0 +1,60 @@ +project(filesystem VERSION 0.0.0 LANGUAGES CXX) + +set(INC_DIR "${CMAKE_CURRENT_BINARY_DIR}/include") +set(HEADER_DIR "${INC_DIR}/${PROJECT_NAME}") + +function(generate_header FS_HEADER FS_NAMESPACE) + message(STATUS "${PROJECT_NAME}: Using ${FS_NAMESPACE} from ${FS_HEADER}") + set(HEADER_FILE "${HEADER_DIR}/import.h") + configure_file(src/import.h.in "${HEADER_FILE}" @ONLY) + target_sources(${PROJECT_NAME} INTERFACE "${HEADER_FILE}") +endfunction() + +function(use_ghc_fs) + # Don't export GHC symbols from ELF shared objects + set(HEADER_FILE "${HEADER_DIR}/ghc-filesystem.h") + file(STRINGS ghc-filesystem/include/ghc/filesystem.hpp HEADER_DATA NEWLINE_CONSUME NO_HEX_CONVERSION) + string(REPLACE "__attribute__((visibility(\"default\")))" "" HEADER_DATA "${HEADER_DATA}") + file(WRITE "${HEADER_FILE}" ${HEADER_DATA}) + + add_library(${PROJECT_NAME} src/ghc-filesystem.cpp "${HEADER_FILE}") + generate_header("\"filesystem/ghc-filesystem.h\"" "ghc::filesystem") + target_compile_definitions(${PROJECT_NAME} + INTERFACE GHC_FILESYSTEM_FWD + PUBLIC GHC_RAISE_UNICODE_ERRORS GHC_WIN_WSTRING_STRING_TYPE + PRIVATE GHC_FILESYSTEM_IMPLEMENTATION + ) + target_include_directories(${PROJECT_NAME} PUBLIC "${INC_DIR}") +endfunction() + +function(use_platform_fs) + add_library(${PROJECT_NAME} INTERFACE) + generate_header("" "std::filesystem") + target_include_directories(${PROJECT_NAME} INTERFACE "${INC_DIR}") +endfunction() + +if (UNIX AND NOT APPLE) + # with gcc11 on arch and latest ardour we get a crash in std::fs if we use the + # os provided one so keep this as an option but default to off + set(SURGE_FILESYSTEM_FORCE_GHC ON CACHE BOOL "Force GHC filesystem implementation") +else() + set(SURGE_FILESYSTEM_FORCE_GHC OFF CACHE BOOL "Force GHC filesystem implementation") +endif() +if (${SURGE_FILESYSTEM_FORCE_GHC}) + use_ghc_fs() +else() + include(CheckCXXSourceCompiles) + check_cxx_source_compiles(" + #include + namespace fs = std::filesystem; + int main(int, char **argv) { + return fs::recursive_directory_iterator{fs::path{*argv}}.depth(); + }" SURGE_FILESYSTEM_STD_FS_FOUND) + if (SURGE_FILESYSTEM_STD_FS_FOUND) + use_platform_fs() + else() + use_ghc_fs() + endif() +endif() + +add_library(surge::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) diff --git a/libs/filesystem/ghc-filesystem b/libs/filesystem/ghc-filesystem new file mode 160000 index 00000000000..8166dd1546c --- /dev/null +++ b/libs/filesystem/ghc-filesystem @@ -0,0 +1 @@ +Subproject commit 8166dd1546c620cfdd4f1bc1d1cd723a91b8f390 diff --git a/libs/filesystem/src/ghc-filesystem.cpp b/libs/filesystem/src/ghc-filesystem.cpp new file mode 100644 index 00000000000..c24a6f15b27 --- /dev/null +++ b/libs/filesystem/src/ghc-filesystem.cpp @@ -0,0 +1,16 @@ +/* +** Surge Synthesizer is Free and Open Source Software +** +** Surge is made available under the Gnu General Public License, v3.0 +** https://www.gnu.org/licenses/gpl-3.0.en.html +** +** Copyright 2004-2021 by various individuals as described by the Git transaction log +** +** All source at: https://github.com/surge-synthesizer/surge.git +** +** Surge was a commercial product from 2004-2018, with Copyright and ownership +** in that period held by Claes Johanson at Vember Audio. Claes made Surge +** open source in September 2018. +*/ + +#include "filesystem/import.h" diff --git a/libs/filesystem/src/import.h.in b/libs/filesystem/src/import.h.in new file mode 100644 index 00000000000..ed6b2352947 --- /dev/null +++ b/libs/filesystem/src/import.h.in @@ -0,0 +1,34 @@ +#pragma once + +/* +** This file imports filesystem and sets the fs namespace to the correct +** thing. In a distant future where we are compiling with all our compilers +** and sdks set up to have std::filesystem this will go away. But while still +** supporting VS2017 and macos 10.12 and stuff we need it. +*/ + +#include @FS_HEADER@ +namespace fs = @FS_NAMESPACE@; + +#include + +inline std::string path_to_string(const fs::path& path) +{ +#ifdef _WIN32 + return path.u8string(); +#else + return path.generic_string(); +#endif +} + +template +inline fs::path string_to_path(T&& path) +{ +#ifdef _WIN32 + return fs::u8path(std::forward(path)); +#else + return fs::path(std::forward(path)); +#endif +} + +void string_to_path(fs::path) = delete; diff --git a/libs/sst/sst-cpputils b/libs/sst/sst-cpputils deleted file mode 160000 index 916c8cdf516..00000000000 --- a/libs/sst/sst-cpputils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 916c8cdf516ec13a11145b8efa6b7ee98146bdca diff --git a/libs/sst/sst-plugininfra b/libs/sst/sst-plugininfra deleted file mode 160000 index c6976768deb..00000000000 --- a/libs/sst/sst-plugininfra +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c6976768debe045505fc07d73afb502b51717120 diff --git a/libs/strnatcmp/strnatcmp.cpp b/libs/strnatcmp/strnatcmp.cpp index 612555bd339..74cbb61a541 100644 --- a/libs/strnatcmp/strnatcmp.cpp +++ b/libs/strnatcmp/strnatcmp.cpp @@ -20,6 +20,7 @@ 3. This notice may not be removed or altered from any source distribution. */ + /* partial change history: * * 2004-10-10 mbp: Lift out character type dependencies into macros. @@ -36,150 +37,142 @@ #include "strnatcmp.h" + /* These are defined as macros to make it easier to adapt this code to * different characters types or comparison functions. */ -static inline int nat_isdigit(nat_char a) { return isdigit((unsigned char)a); } +static inline int +nat_isdigit(nat_char a) +{ + return isdigit((unsigned char) a); +} + -static inline int nat_isspace(nat_char a) { return isspace((unsigned char)a); } +static inline int +nat_isspace(nat_char a) +{ + return isspace((unsigned char) a); +} -static inline nat_char nat_toupper(nat_char a) { return toupper((unsigned char)a); } -static int compare_right(nat_char const *a, nat_char const *b) +static inline nat_char +nat_toupper(nat_char a) { - int bias = 0; - - /* The longest run of digits wins. That aside, the greatest - value wins, but we can't know that it will until we've scanned - both numbers to know that they have the same magnitude, so we - remember it in BIAS. */ - for (;; a++, b++) - { - if (!nat_isdigit(*a) && !nat_isdigit(*b)) - return bias; - else if (!nat_isdigit(*a)) - return -1; - else if (!nat_isdigit(*b)) - return +1; - else if (*a < *b) - { - if (!bias) - bias = -1; - } - else if (*a > *b) - { - if (!bias) - bias = +1; - } - else if (!*a && !*b) - return bias; - } - - return 0; + return toupper((unsigned char) a); } -static int compare_left(nat_char const *a, nat_char const *b) + + +static int +compare_right(nat_char const *a, nat_char const *b) { - /* Compare two left-aligned numbers: the first to have a - different value wins. */ - for (;; a++, b++) - { - if (!nat_isdigit(*a) && !nat_isdigit(*b)) - return 0; - else if (!nat_isdigit(*a)) - return -1; - else if (!nat_isdigit(*b)) - return +1; - else if (*a < *b) - return -1; - else if (*a > *b) - return +1; - } - - return 0; + int bias = 0; + + /* The longest run of digits wins. That aside, the greatest + value wins, but we can't know that it will until we've scanned + both numbers to know that they have the same magnitude, so we + remember it in BIAS. */ + for (;; a++, b++) { + if (!nat_isdigit(*a) && !nat_isdigit(*b)) + return bias; + else if (!nat_isdigit(*a)) + return -1; + else if (!nat_isdigit(*b)) + return +1; + else if (*a < *b) { + if (!bias) + bias = -1; + } else if (*a > *b) { + if (!bias) + bias = +1; + } else if (!*a && !*b) + return bias; + } + + return 0; } + +static int +compare_left(nat_char const *a, nat_char const *b) +{ + /* Compare two left-aligned numbers: the first to have a + different value wins. */ + for (;; a++, b++) { + if (!nat_isdigit(*a) && !nat_isdigit(*b)) + return 0; + else if (!nat_isdigit(*a)) + return -1; + else if (!nat_isdigit(*b)) + return +1; + else if (*a < *b) + return -1; + else if (*a > *b) + return +1; + } + + return 0; +} + + static int strnatcmp0(nat_char const *a, nat_char const *b, int fold_case) { - int ai, bi; - nat_char ca, cb; - int fractional, result; - - assert(a && b); - ai = bi = 0; - - // Modification: Strip all leading spaces and any consecutive internal spaces - bool fa{true}, fb{true}; - while (1) - { - ca = a[ai]; - cb = b[bi]; - - /* skip over leading spaces or zeros */ - if (fa) - { - while (nat_isspace(ca)) - ca = a[++ai]; - } - else - { - while (ca && nat_isspace(ca) && nat_isspace(a[ai + 1])) - ca = a[++ai]; - } - fa = false; - - if (fb) - { - while (nat_isspace(cb)) - cb = b[++bi]; - } - else - { - while (cb && nat_isspace(cb) && nat_isspace(b[bi + 1])) - cb = b[++bi]; - } - fb = false; - - /* process run of digits */ - if (nat_isdigit(ca) && nat_isdigit(cb)) - { - fractional = (ca == '0' || cb == '0'); - - if (fractional) - { - if ((result = compare_left(a + ai, b + bi)) != 0) - return result; - } - else - { - if ((result = compare_right(a + ai, b + bi)) != 0) - return result; - } - } - - if (!ca && !cb) - { - /* The strings compare the same. Perhaps the caller - will want to call strcmp to break the tie. */ - return 0; - } - - if (fold_case) - { - ca = nat_toupper(ca); - cb = nat_toupper(cb); - } - - if (ca < cb) - return -1; - else if (ca > cb) - return +1; - - ++ai; - ++bi; - } + int ai, bi; + nat_char ca, cb; + int fractional, result; + + assert(a && b); + ai = bi = 0; + while (1) { + ca = a[ai]; cb = b[bi]; + + /* skip over leading spaces or zeros */ + while (nat_isspace(ca)) + ca = a[++ai]; + + while (nat_isspace(cb)) + cb = b[++bi]; + + /* process run of digits */ + if (nat_isdigit(ca) && nat_isdigit(cb)) { + fractional = (ca == '0' || cb == '0'); + + if (fractional) { + if ((result = compare_left(a+ai, b+bi)) != 0) + return result; + } else { + if ((result = compare_right(a+ai, b+bi)) != 0) + return result; + } + } + + if (!ca && !cb) { + /* The strings compare the same. Perhaps the caller + will want to call strcmp to break the tie. */ + return 0; + } + + if (fold_case) { + ca = nat_toupper(ca); + cb = nat_toupper(cb); + } + + if (ca < cb) + return -1; + else if (ca > cb) + return +1; + + ++ai; ++bi; + } +} + + + +int strnatcmp(nat_char const *a, nat_char const *b) { + return strnatcmp0(a, b, 0); } -int strnatcmp(nat_char const *a, nat_char const *b) { return strnatcmp0(a, b, 0); } /* Compare, recognizing numeric string and ignoring case. */ -int strnatcasecmp(nat_char const *a, nat_char const *b) { return strnatcmp0(a, b, 1); } +int strnatcasecmp(nat_char const *a, nat_char const *b) { + return strnatcmp0(a, b, 1); +} diff --git a/libs/tinyxml/CMakeLists.txt b/libs/tinyxml/CMakeLists.txt new file mode 100644 index 00000000000..8dd8c3f9e79 --- /dev/null +++ b/libs/tinyxml/CMakeLists.txt @@ -0,0 +1,12 @@ +project(tinyxml) + +add_library(${PROJECT_NAME} + src/tinyxmlparser.cpp + src/tinyxml.cpp + src/tinyxmlerror.cpp + include/${PROJECT_NAME}/tinyxml.h +) +add_library(surge::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) +target_link_libraries(${PROJECT_NAME} PUBLIC surge::filesystem) +target_compile_definitions(${PROJECT_NAME} PUBLIC TIXML_USE_STL) +target_include_directories(${PROJECT_NAME} PUBLIC include) diff --git a/libs/tinyxml/include/tinyxml/tinystr.h b/libs/tinyxml/include/tinyxml/tinystr.h new file mode 100644 index 00000000000..b380fad9655 --- /dev/null +++ b/libs/tinyxml/include/tinyxml/tinystr.h @@ -0,0 +1,242 @@ +/* +www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "tinyxml/tinyxml.h" + + +#ifndef TIXML_USE_STL + +#ifndef TIXML_STRING_INCLUDED +#define TIXML_STRING_INCLUDED + +#ifdef _MSC_VER +#pragma warning( disable : 4786 ) // Debugger truncating names. +#endif + +#include + +/* + TiXmlString is an emulation of the std::string template. + Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. + Only the member functions relevant to the TinyXML project have been implemented. + The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase + a string and there's no more room, we allocate a buffer twice as big as we need. +*/ +class TiXmlString +{ + public : + // TiXmlString constructor, based on a string + TiXmlString (const char * instring); + + // TiXmlString empty constructor + TiXmlString () + { + allocated = 0; + cstring = NULL; + current_length = 0; + } + + // TiXmlString copy constructor + TiXmlString (const TiXmlString& copy); + + // TiXmlString destructor + ~ TiXmlString () + { + empty_it (); + } + + // Convert a TiXmlString into a classical char * + const char * c_str () const + { + if (allocated) + return cstring; + return ""; + } + + // Return the length of a TiXmlString + unsigned length () const + { + return ( allocated ) ? current_length : 0; + } + + // TiXmlString = operator + void operator = (const char * content); + + // = operator + void operator = (const TiXmlString & copy); + + // += operator. Maps to append + TiXmlString& operator += (const char * suffix) + { + append (suffix); + return *this; + } + + // += operator. Maps to append + TiXmlString& operator += (char single) + { + append (single); + return *this; + } + + // += operator. Maps to append + TiXmlString& operator += (TiXmlString & suffix) + { + append (suffix); + return *this; + } + bool operator == (const TiXmlString & compare) const; + bool operator < (const TiXmlString & compare) const; + bool operator > (const TiXmlString & compare) const; + + // Checks if a TiXmlString is empty + bool empty () const + { + return length () ? false : true; + } + + // single char extraction + const char& at (unsigned index) const + { + assert( index < length ()); + return cstring [index]; + } + + // find a char in a string. Return TiXmlString::notfound if not found + unsigned find (char lookup) const + { + return find (lookup, 0); + } + + // find a char in a string from an offset. Return TiXmlString::notfound if not found + unsigned find (char tofind, unsigned offset) const; + + /* Function to reserve a big amount of data when we know we'll need it. Be aware that this + function clears the content of the TiXmlString if any exists. + */ + void reserve (unsigned size) + { + empty_it (); + if (size) + { + allocated = size; + cstring = new char [size]; + cstring [0] = 0; + current_length = 0; + } + } + + // [] operator + char& operator [] (unsigned index) const + { + assert( index < length ()); + return cstring [index]; + } + + // Error value for find primitive + enum { notfound = 0xffffffff, + npos = notfound }; + + void append (const char *str, int len ); + + protected : + + // The base string + char * cstring; + // Number of chars allocated + unsigned allocated; + // Current string size + unsigned current_length; + + // New size computation. It is simplistic right now : it returns twice the amount + // we need + unsigned assign_new_size (unsigned minimum_to_allocate) + { + return minimum_to_allocate * 2; + } + + // Internal function that clears the content of a TiXmlString + void empty_it () + { + if (cstring) + delete [] cstring; + cstring = NULL; + allocated = 0; + current_length = 0; + } + + void append (const char *suffix ); + + // append function for another TiXmlString + void append (const TiXmlString & suffix) + { + append (suffix . c_str ()); + } + + // append for a single char. + void append (char single) + { + if ( cstring && current_length < (allocated-1) ) + { + cstring[ current_length ] = single; + ++current_length; + cstring[ current_length ] = 0; + } + else + { + char smallstr [2]; + smallstr [0] = single; + smallstr [1] = 0; + append (smallstr); + } + } + +} ; + +/* + TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. + Only the operators that we need for TinyXML have been developped. +*/ +class TiXmlOutStream : public TiXmlString +{ +public : + TiXmlOutStream () : TiXmlString () {} + + // TiXmlOutStream << operator. Maps to TiXmlString::append + TiXmlOutStream & operator << (const char * in) + { + append (in); + return (* this); + } + + // TiXmlOutStream << operator. Maps to TiXmlString::append + TiXmlOutStream & operator << (const TiXmlString & in) + { + append (in . c_str ()); + return (* this); + } +} ; + +#endif // TIXML_STRING_INCLUDED +#endif // TIXML_USE_STL diff --git a/libs/tinyxml/include/tinyxml/tinyxml.h b/libs/tinyxml/include/tinyxml/tinyxml.h new file mode 100644 index 00000000000..a6005011504 --- /dev/null +++ b/libs/tinyxml/include/tinyxml/tinyxml.h @@ -0,0 +1,1397 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#ifndef TINYXML_INCLUDED +#define TINYXML_INCLUDED + +#include +#include + +#ifdef TIXML_USE_STL + #include "filesystem/import.h" + #include + #include + #define TIXML_STRING std::string + #define TIXML_ISTREAM std::istream + #define TIXML_OSTREAM std::ostream +#else + #include "tinystr.h" + #define TIXML_STRING TiXmlString + #define TIXML_OSTREAM TiXmlOutStream +#endif + +class TiXmlDocument; +class TiXmlElement; +class TiXmlComment; +class TiXmlUnknown; +class TiXmlAttribute; +class TiXmlText; +class TiXmlDeclaration; +class TiXmlParsingData; + +const int TIXML_MAJOR_VERSION = 2; +const int TIXML_MINOR_VERSION = 3; +const int TIXML_PATCH_VERSION = 3; + +/* Internal structure for tracking location of items + in the XML file. +*/ +struct TiXmlCursor +{ + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } + + int row; // 0 based. + int col; // 0 based. +}; + + +// Only used by Attribute::Query functions +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE +}; + + +// Used by the parsing routines. +enum TiXmlEncoding +{ + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY +}; + +const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; + +/** TiXmlBase is a base class for every class in TinyXml. + It does little except to establish that TinyXml classes + can be printed and provide some utility functions. + + In XML, the document and elements can contain + other elements and other types of nodes. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + A Decleration contains: Attributes (not on tree) + @endverbatim +*/ +class TiXmlBase +{ + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; + +public: + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a stream. + This is a formatted print, and will insert tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( TIXML_OSTREAM& cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + values is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { return location.row + 1; } + int Column() const { return location.col + 1; } ///< See Row() + + void SetUserData( void* user ) { userData = user; } + void* GetUserData() { return userData; } + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_OUT_OF_MEMORY, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + + TIXML_ERROR_STRING_COUNT + }; + +protected: + + // See STL_STRING_BUG + // Utility class to overcome a bug. + class StringToBuffer + { + public: + StringToBuffer( const TIXML_STRING& str ); + ~StringToBuffer(); + char* buffer; + }; + + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + inline static bool IsWhiteSpace( char c ) + { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + + virtual void StreamOut (TIXML_OSTREAM *) const = 0; + + #ifdef TIXML_USE_STL + static bool StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag ); + static bool StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag ); + #endif + + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) + { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) + { + *length = utf8ByteTable[ *((unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } + else + { + *length = 1; + } + + if ( *length == 1 ) + { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } + else if ( *length ) + { + strncpy( _value, p, *length ); + return p + (*length); + } + else + { + // Not valid text. + return 0; + } + } + + // Puts a string to a stream, expanding entities as it goes. + // Note this should not contian the '<', '>', etc, or they will be transformed into entities! + static void PutString( const TIXML_STRING& str, TIXML_OSTREAM* out ); + + static void PutString( const TIXML_STRING& str, TIXML_STRING* out ); + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to Engilish words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; + + /// Field containing a generic user pointer + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) + { + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( v < 128 ) return tolower( v ); + return v; + } + else + { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + +private: + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity + { + const char* str; + unsigned int strLength; + char chr; + }; + enum + { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; +}; + + +/** The parent class for everything in the Document Object Model. + (Except for attributes). + Nodes have siblings, a parent, and children. A node can be + in a document, or stand on its own. The type of a TiXmlNode + can be queried, and it can be cast to its more defined type. +*/ +class TiXmlNode : public TiXmlBase +{ + friend class TiXmlDocument; + friend class TiXmlElement; + +public: + #ifdef TIXML_USE_STL + + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); + + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. + + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. + + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); + + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); + + #else + // Used internally, not part of the public API. + friend TIXML_OSTREAM& operator<< (TIXML_OSTREAM& out, const TiXmlNode& base); + #endif + + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + DOCUMENT, + ELEMENT, + COMMENT, + UNKNOWN, + TEXT, + DECLARATION, + TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char * Value() const { return value.c_str (); } + + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char * _value) { value = _value;} + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetValue( const std::string& _value ) + { + StringToBuffer buf( _value ); + SetValue( buf.buffer ? buf.buffer : "" ); + } + #endif + + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { return parent; } + const TiXmlNode* Parent() const { return parent; } + + const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild() { return firstChild; } + const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char * value ); ///< The first child of this node with the matching 'value'. Will be null if none found. + + const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild() { return lastChild; } + const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char * value ); + + #ifdef TIXML_USE_STL + const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. + #endif + + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( TiXmlNode* previous ); + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char * value, TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char * value, TiXmlNode* previous ); + + #ifdef TIXML_USE_STL + const TiXmlNode* IterateChildren( const std::string& _value, TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + TiXmlNode* IterateChildren( const std::string& _value, TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + #endif + + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + + + /** Add a new node related to this. Adds a child past the LastChild. + + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. + + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); + + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { return prev; } + TiXmlNode* PreviousSibling() { return prev; } + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char * ) const; + TiXmlNode* PreviousSibling( const char * ); + + #ifdef TIXML_USE_STL + const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { return next; } + TiXmlNode* NextSibling() { return next; } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char * ) const; + TiXmlNode* NextSibling( const char * ); + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement(); + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char * ) const; + TiXmlElement* NextSiblingElement( const char * ); + + #ifdef TIXML_USE_STL + const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement(); + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char * value ) const; + TiXmlElement* FirstChildElement( const char * value ); + + #ifdef TIXML_USE_STL + const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /** Query the type (as an enumerated value, above) of this node. + The possible types are: DOCUMENT, ELEMENT, COMMENT, + UNKNOWN, TEXT, and DECLARATION. + */ + virtual int Type() const { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument(); + + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } + +#if INEEDTHISAND +#define THISAND this && +#else +#define THISAND +#endif + + const TiXmlDocument* ToDocument() const { return ( THISAND type == DOCUMENT ) ? (const TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + const TiXmlElement* ToElement() const { return ( THISAND type == ELEMENT ) ? (const TiXmlElement*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + const TiXmlComment* ToComment() const { return ( THISAND type == COMMENT ) ? (const TiXmlComment*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + const TiXmlUnknown* ToUnknown() const { return ( THISAND type == UNKNOWN ) ? (const TiXmlUnknown*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + const TiXmlText* ToText() const { return ( THISAND type == TEXT ) ? (const TiXmlText*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + const TiXmlDeclaration* ToDeclaration() const { return ( THISAND type == DECLARATION ) ? (const TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + + TiXmlDocument* ToDocument() { return ( THISAND type == DOCUMENT ) ? (TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlElement* ToElement() { return ( THISAND type == ELEMENT ) ? (TiXmlElement*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlComment* ToComment() { return ( THISAND type == COMMENT ) ? (TiXmlComment*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlUnknown* ToUnknown() { return ( THISAND type == UNKNOWN ) ? (TiXmlUnknown*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlText* ToText() { return ( THISAND type == TEXT ) ? (TiXmlText*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlDeclaration* ToDeclaration() { return ( THISAND type == DECLARATION ) ? (TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + +protected: + TiXmlNode( NodeType _type ); + + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; + + #ifdef TIXML_USE_STL + // The real work of the input operator. + virtual void StreamIn( TIXML_ISTREAM* in, TIXML_STRING* tag ) = 0; + #endif + + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + + // Internal Value function returning a TIXML_STRING + const TIXML_STRING& SValue() const { return value ; } + + TiXmlNode* parent; + NodeType type; + + TiXmlNode* firstChild; + TiXmlNode* lastChild; + + TIXML_STRING value; + + TiXmlNode* prev; + TiXmlNode* next; + +private: + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. +}; + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not TiXmlNodes, since they are not + part of the tinyXML document object model. There are other + suggested ways to look at this problem. +*/ +class TiXmlAttribute : public TiXmlBase +{ + friend class TiXmlAttributeSet; + +public: + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() + { + document = 0; + prev = next = 0; + } + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + #endif + + /// Construct an attribute with a name and value. + TiXmlAttribute( const char * _name, const char * _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { return name.c_str (); } ///< Return the name of this attribute. + const char* Value() const { return value.c_str (); } ///< Return the value of this attribute. + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. + + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. + + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* value ) const; + + void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const char* _value ) { value = _value; } ///< Set the value. + + void SetIntValue( int value ); ///< Set the value from an integer. + void SetDoubleValue( double value ); ///< Set the value from a double. + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetName( const std::string& _name ) + { + StringToBuffer buf( _name ); + SetName ( buf.buffer ? buf.buffer : "error" ); + } + /// STL std::string form. + void SetValue( const std::string& _value ) + { + StringToBuffer buf( _value ); + SetValue( buf.buffer ? buf.buffer : "error" ); + } + #endif + + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next(); + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous(); + + bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } + bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } + bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; + + // Prints this Attribute to a stream. + virtual void Print( TIXML_OSTREAM& cfile, int depth ) const override; + + virtual void StreamOut( TIXML_OSTREAM * out ) const override; + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } + +private: + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; +}; + + +/* A class used to manage a group of attributes. + It is only used internally, both by the ELEMENT and the DECLARATION. + + The set can be changed transparent to the Element and Declaration + classes that use it, but NOT transparent to the Attribute + which has to implement a next() and previous() method. Which makes + it a bit problematic and prevents the use of STL. + + This version is implemented with circular lists because: + - I like circular lists + - it demonstrates some independence from the (typical) doubly linked list. +*/ +class TiXmlAttributeSet +{ +public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); + + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); + + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + + const TiXmlAttribute* Find( const char * name ) const; + TiXmlAttribute* Find( const char * name ); + +private: + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) + + TiXmlAttribute sentinel; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TiXmlElement : public TiXmlNode +{ +public: + /// Construct an element. + TiXmlElement (const char * in_value); + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlElement( const std::string& _value ); + #endif + + TiXmlElement( const TiXmlElement& ); + + void operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* value ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, float* value ) const { + double d; + int result = QueryDoubleAttribute( name, &d ); + *value = (float)d; + return result; + } + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char * value ); + + #ifdef TIXML_USE_STL + const char* Attribute( const std::string& name ) const { return Attribute( name.c_str() ); } + const char* Attribute( const std::string& name, int* i ) const { return Attribute( name.c_str(), i ); } + const char* Attribute( const std::string& name, double* d ) const { return Attribute( name.c_str(), d ); } + int QueryIntAttribute( const std::string& name, int* value ) const { return QueryIntAttribute( name.c_str(), value ); } + int QueryDoubleAttribute( const std::string& name, double* value ) const { return QueryDoubleAttribute( name.c_str(), value ); } + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ) + { + StringToBuffer n( name ); + StringToBuffer v( _value ); + if ( n.buffer && v.buffer ) + SetAttribute (n.buffer, v.buffer ); + } + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ) + { + StringToBuffer n( name ); + if ( n.buffer ) + SetAttribute (n.buffer, _value); + } + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char * name, int value ); + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char * name, double value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char * name ); + #ifdef TIXML_USE_STL + void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. + #endif + + const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } + const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const override; + // Print the Element to a stream. + virtual void Print( TIXML_OSTREAM& cfile, int depth ) const override; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; + +protected: + + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well + + // Used to be public [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) override; + #endif + virtual void StreamOut( TIXML_OSTREAM * out ) const override; + + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + +private: + + TiXmlAttributeSet attributeSet; +}; + + +/** An XML comment. +*/ +class TiXmlComment : public TiXmlNode +{ +public: + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} + TiXmlComment( const TiXmlComment& ); + void operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const override; + /// Write this Comment to a stream. + virtual void Print( TIXML_OSTREAM& cfile, int depth ) const override; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; + +protected: + void CopyTo( TiXmlComment* target ) const; + + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) override; + #endif + virtual void StreamOut( TIXML_OSTREAM * out ) const override; + +private: + +}; + + +/** XML text. Contained in an element. +*/ +class TiXmlText : public TiXmlNode +{ + friend class TiXmlElement; +public: + /// Constructor. + TiXmlText (const char * initValue) : TiXmlNode (TiXmlNode::TEXT) + { + SetValue( initValue ); + } + virtual ~TiXmlText() {} + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) + { + SetValue( initValue ); + } + #endif + + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } + void operator=( const TiXmlText& base ) { base.CopyTo( this ); } + + /// Write this text object to a stream. + virtual void Print( TIXML_OSTREAM& cfile, int depth ) const override; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; + +protected : + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const override; + void CopyTo( TiXmlText* target ) const; + + virtual void StreamOut ( TIXML_OSTREAM * out ) const override; + bool Blank() const; // returns true if all white space and new lines + // [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) override; + #endif + +private: +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXml will happily read or write files without a declaration, + however. There are 3 possible attributes to the declaration: + version, encoding, and standalone. + + Note: In this version of the code, the attributes are + handled as special cases, not generic attributes, simply + because there can only be at most 3 and they are always the same. +*/ +class TiXmlDeclaration : public TiXmlNode +{ +public: + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} + +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); +#endif + + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + void operator=( const TiXmlDeclaration& copy ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return an empty string if none was found. + const char *Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char *Standalone() const { return standalone.c_str (); } + + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const override; + /// Print this declaration to a stream. + virtual void Print( TIXML_OSTREAM& cfile, int depth ) const override; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; + +protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) override; + #endif + virtual void StreamOut ( TIXML_OSTREAM * out) const override; + +private: + + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; +}; + + +/** Any tag that tinyXml doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into TiXmlUnknowns. +*/ +class TiXmlUnknown : public TiXmlNode +{ +public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } + void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } + + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const override; + /// Print this Unknown to a stream. + virtual void Print( TIXML_OSTREAM& cfile, int depth ) const override; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; + +protected: + void CopyTo( TiXmlUnknown* target ) const; + + #ifdef TIXML_USE_STL + virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) override; + #endif + virtual void StreamOut ( TIXML_OSTREAM * out ) const override; + +private: + +}; + + +/** Always the top level node. A document binds together all the + XML pieces. It can be saved, loaded, and printed to the screen. + The 'value' of a document node is the xml file name. +*/ +class TiXmlDocument : public TiXmlNode +{ +public: + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char * documentName ); + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlDocument( const std::string& documentName ); + #endif + + TiXmlDocument( const TiXmlDocument& copy ); + void operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; +#ifndef TIXML_USE_STL + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char * filename ) const; +#else // !TIXML_USE_STL + bool LoadFile( const fs::path& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + bool SaveFile( const fs::path& filename ) const; +#endif // TIXML_USE_STL + + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) override; + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { return FirstChildElement(); } + TiXmlElement* RootElement() { return FirstChildElement(); } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { return error; } + + /// Contains a textual (english) description of the error if one occurs. + const char * ErrorDesc() const { return errorDesc.c_str (); } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { return errorId; } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() { return errorLocation.row+1; } + int ErrorCol() { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() + + /** By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { tabsize = _tabsize; } + + int TabSize() const { return tabsize; } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() { error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /// Print this Document to a stream. + virtual void Print( TIXML_OSTREAM& cfile, int depth = 0 ) const override; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + +protected : + virtual void StreamOut ( TIXML_OSTREAM * out) const override; + // [internal use] + virtual TiXmlNode* Clone() const override; + #ifdef TIXML_USE_STL + virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) override; + #endif + +private: + void CopyTo( TiXmlDocument* target ) const; + + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; +}; + + +/** + A TiXmlHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + TiXmlElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + TiXmlElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + TiXmlElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + TiXmlElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + TiXmlHandle docHandle( &document ); + TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).Element(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + TiXmlHandle handleCopy = handle; + @endverbatim + + What they should not be used for is iteration: + + @verbatim + int i=0; + while ( true ) + { + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).Element(); + if ( !child ) + break; + // do something + ++i; + } + @endverbatim + + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs + to. Instead, prefer: + + @verbatim + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).Element(); + + for( child; child; child=child->NextSiblingElement() ) + { + // do something + } + @endverbatim +*/ +class TiXmlHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* node ) { this->node = node; } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char * value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char * value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; + + #ifdef TIXML_USE_STL + TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } + TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } + + TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } + #endif + + /// Return the handle as a TiXmlNode. This may return null. + TiXmlNode* Node() const { return node; } + /// Return the handle as a TiXmlElement. This may return null. + TiXmlElement* Element() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /// Return the handle as a TiXmlText. This may return null. + TiXmlText* Text() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /// Return the handle as a TiXmlUnknown. This may return null; + TiXmlUnknown* Unknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + +private: + TiXmlNode* node; +}; + + +#endif + diff --git a/libs/tinyxml/src/tinystr.cpp b/libs/tinyxml/src/tinystr.cpp new file mode 100644 index 00000000000..bd246156deb --- /dev/null +++ b/libs/tinyxml/src/tinystr.cpp @@ -0,0 +1,306 @@ +/* +www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "tinyxml/tinyxml.h" + +#ifndef TIXML_USE_STL + + +#include +#include +#include + +#include "tinyxml/tinystr.h" + +// TiXmlString constructor, based on a C string +TiXmlString::TiXmlString (const char* instring) +{ + unsigned newlen; + char * newstring; + + if (!instring) + { + allocated = 0; + cstring = NULL; + current_length = 0; + return; + } + //*ME: warning C4267: convert 'size_t' to 'unsigned int' + //*ME: Use Cast: (unsigned) + newlen = (unsigned)strlen (instring) + 1; + newstring = new char [newlen]; + memcpy (newstring, instring, newlen); + // strcpy (newstring, instring); + allocated = newlen; + cstring = newstring; + current_length = newlen - 1; +} + +// TiXmlString copy constructor +TiXmlString::TiXmlString (const TiXmlString& copy) +{ + unsigned newlen; + char * newstring; + + // Prevent copy to self! + if ( © == this ) + return; + + if (! copy . allocated) + { + allocated = 0; + cstring = NULL; + current_length = 0; + return; + } + newlen = copy . length () + 1; + newstring = new char [newlen]; + // strcpy (newstring, copy . cstring); + memcpy (newstring, copy . cstring, newlen); + allocated = newlen; + cstring = newstring; + current_length = newlen - 1; +} + +// TiXmlString = operator. Safe when assign own content +void TiXmlString ::operator = (const char * content) +{ + unsigned newlen; + char * newstring; + + if (! content) + { + empty_it (); + return; + } + newlen = (unsigned)strlen (content) + 1; + newstring = new char [newlen]; + // strcpy (newstring, content); + memcpy (newstring, content, newlen); + empty_it (); + allocated = newlen; + cstring = newstring; + current_length = newlen - 1; +} + +// = operator. Safe when assign own content +void TiXmlString ::operator = (const TiXmlString & copy) +{ + unsigned newlen; + char * newstring; + + if (! copy . length ()) + { + empty_it (); + return; + } + newlen = copy . length () + 1; + newstring = new char [newlen]; + // strcpy (newstring, copy . c_str ()); + memcpy (newstring, copy . c_str (), newlen); + empty_it (); + allocated = newlen; + cstring = newstring; + current_length = newlen - 1; +} + + +// append a const char * to an existing TiXmlString +void TiXmlString::append( const char* str, int len ) +{ + char * new_string; + unsigned new_alloc, new_size, size_suffix; + + // don't use strlen - it can overrun the len passed in! + const char* p = str; + size_suffix = 0; + + while ( *p && size_suffix < (unsigned)len ) + { + ++p; + ++size_suffix; + } + if ( !size_suffix) + return; + + new_size = length () + size_suffix + 1; + // check if we need to expand + if (new_size > allocated) + { + // compute new size + new_alloc = assign_new_size (new_size); + + // allocate new buffer + new_string = new char [new_alloc]; + new_string [0] = 0; + + // copy the previous allocated buffer into this one + if (allocated && cstring) + // strcpy (new_string, cstring); + memcpy (new_string, cstring, length ()); + + // append the suffix. It does exist, otherwize we wouldn't be expanding + // strncat (new_string, str, len); + memcpy (new_string + length (), + str, + size_suffix); + + // return previsously allocated buffer if any + if (allocated && cstring) + delete [] cstring; + + // update member variables + cstring = new_string; + allocated = new_alloc; + } + else + { + // we know we can safely append the new string + // strncat (cstring, str, len); + memcpy (cstring + length (), + str, + size_suffix); + } + current_length = new_size - 1; + cstring [current_length] = 0; +} + + +// append a const char * to an existing TiXmlString +void TiXmlString::append( const char * suffix ) +{ + char * new_string; + unsigned new_alloc, new_size; + + new_size = length () + strlen (suffix) + 1; + // check if we need to expand + if (new_size > allocated) + { + // compute new size + new_alloc = assign_new_size (new_size); + + // allocate new buffer + new_string = new char [new_alloc]; + new_string [0] = 0; + + // copy the previous allocated buffer into this one + if (allocated && cstring) + memcpy (new_string, cstring, 1 + length ()); + // strcpy (new_string, cstring); + + // append the suffix. It does exist, otherwize we wouldn't be expanding + // strcat (new_string, suffix); + memcpy (new_string + length (), + suffix, + strlen (suffix) + 1); + + // return previsously allocated buffer if any + if (allocated && cstring) + delete [] cstring; + + // update member variables + cstring = new_string; + allocated = new_alloc; + } + else + { + // we know we can safely append the new string + // strcat (cstring, suffix); + memcpy (cstring + length (), + suffix, + strlen (suffix) + 1); + } + current_length = new_size - 1; +} + +// Check for TiXmlString equuivalence +//bool TiXmlString::operator == (const TiXmlString & compare) const +//{ +// return (! strcmp (c_str (), compare . c_str ())); +//} + +//unsigned TiXmlString::length () const +//{ +// if (allocated) +// // return strlen (cstring); +// return current_length; +// return 0; +//} + + +unsigned TiXmlString::find (char tofind, unsigned offset) const +{ + //*ME: warning C4244: convert '__w64 int' to 'unsigned' + //*ME: Use Array-Arithmetic instead of Pointer + // char * lookup; + + if (offset >= length ()) + return (unsigned) notfound; + // for (lookup = cstring + offset; * lookup; lookup++) + // if (* lookup == tofind) + // return lookup - cstring; + for( unsigned n=offset ; cstring[n] != '\0' ; n++ ) + if( cstring[n] == tofind ) + return n ; + return (unsigned) notfound; +} + + +bool TiXmlString::operator == (const TiXmlString & compare) const +{ + if ( allocated && compare.allocated ) + { + assert( cstring ); + assert( compare.cstring ); + return ( strcmp( cstring, compare.cstring ) == 0 ); + } + return false; +} + + +bool TiXmlString::operator < (const TiXmlString & compare) const +{ + if ( allocated && compare.allocated ) + { + assert( cstring ); + assert( compare.cstring ); + return ( strcmp( cstring, compare.cstring ) > 0 ); + } + return false; +} + + +bool TiXmlString::operator > (const TiXmlString & compare) const +{ + if ( allocated && compare.allocated ) + { + assert( cstring ); + assert( compare.cstring ); + return ( strcmp( cstring, compare.cstring ) < 0 ); + } + return false; +} + + +#endif // TIXML_USE_STL diff --git a/libs/tinyxml/src/tinyxml.cpp b/libs/tinyxml/src/tinyxml.cpp new file mode 100644 index 00000000000..2905d5a995a --- /dev/null +++ b/libs/tinyxml/src/tinyxml.cpp @@ -0,0 +1,1658 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "tinyxml/tinyxml.h" + +#include +#include +#include +#include + +bool TiXmlBase::condenseWhiteSpace = true; + +void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream ) +{ + TIXML_STRING buffer; + PutString( str, &buffer ); + (*stream) << buffer; +} + +void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString ) +{ + int i=0; + + while( i<(int)str.length() ) + { + unsigned char c = (unsigned char) str[i]; + + if ( c == '&' + && i < ( (int)str.length() - 2 ) + && str[i+1] == '#' + && str[i+2] == 'x' ) + { + // Hexadecimal character reference. + // Pass through unchanged. + // © -- copyright symbol, for example. + // + // The -1 is a bug fix from Rob Laveaux. It keeps + // an overflow from happening if there is no ';'. + // There are actually 2 ways to exit this loop - + // while fails (error case) and break (semicolon found). + // However, there is no mechanism (currently) for + // this function to return an error. + while ( i<(int)str.length()-1 ) + { + outString->append( str.c_str() + i, 1 ); + ++i; + if ( str[i] == ';' ) + break; + } + } + else if ( c == '&' ) + { + outString->append( entity[0].str, entity[0].strLength ); + ++i; + } + else if ( c == '<' ) + { + outString->append( entity[1].str, entity[1].strLength ); + ++i; + } + else if ( c == '>' ) + { + outString->append( entity[2].str, entity[2].strLength ); + ++i; + } + else if ( c == '\"' ) + { + outString->append( entity[3].str, entity[3].strLength ); + ++i; + } + else if ( c == '\'' ) + { + outString->append( entity[4].str, entity[4].strLength ); + ++i; + } + else if ( c < 32 ) + { + // Easy pass at non-alpha/numeric/symbol + // Below 32 is symbolic. + char buf[ 32 ]; + sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); + //*ME: warning C4267: convert 'size_t' to 'int' + //*ME: Int-Cast to make compiler happy ... + outString->append( buf, (int)strlen( buf ) ); + ++i; + } + else + { + //char realc = (char) c; + //outString->append( &realc, 1 ); + *outString += (char) c; // somewhat more efficient function call. + ++i; + } + } +} + + +// <-- Strange class for a bug fix. Search for STL_STRING_BUG +TiXmlBase::StringToBuffer::StringToBuffer( const TIXML_STRING& str ) +{ + buffer = new char[ str.length()+1 ]; + if ( buffer ) + { + strcpy( buffer, str.c_str() ); + } +} + + +TiXmlBase::StringToBuffer::~StringToBuffer() +{ + delete [] buffer; +} +// End strange bug fix. --> + + +TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() +{ + parent = 0; + type = _type; + firstChild = 0; + lastChild = 0; + prev = 0; + next = 0; +} + + +TiXmlNode::~TiXmlNode() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } +} + + +void TiXmlNode::CopyTo( TiXmlNode* target ) const +{ + target->SetValue (value.c_str() ); + target->userData = userData; +} + + +void TiXmlNode::Clear() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } + + firstChild = 0; + lastChild = 0; +} + + +TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) +{ + node->parent = this; + + node->prev = lastChild; + node->next = 0; + + if ( lastChild ) + lastChild->next = node; + else + firstChild = node; // it was an empty list. + + lastChild = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) +{ + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + + return LinkEndChild( node ); +} + + +TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) +{ + if ( !beforeThis || beforeThis->parent != this ) + return 0; + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->next = beforeThis; + node->prev = beforeThis->prev; + if ( beforeThis->prev ) + { + beforeThis->prev->next = node; + } + else + { + assert( firstChild == beforeThis ); + firstChild = node; + } + beforeThis->prev = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) +{ + if ( !afterThis || afterThis->parent != this ) + return 0; + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->prev = afterThis; + node->next = afterThis->next; + if ( afterThis->next ) + { + afterThis->next->prev = node; + } + else + { + assert( lastChild == afterThis ); + lastChild = node; + } + afterThis->next = node; + return node; +} + + +TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) +{ + if ( replaceThis->parent != this ) + return 0; + + TiXmlNode* node = withThis.Clone(); + if ( !node ) + return 0; + + node->next = replaceThis->next; + node->prev = replaceThis->prev; + + if ( replaceThis->next ) + replaceThis->next->prev = node; + else + lastChild = node; + + if ( replaceThis->prev ) + replaceThis->prev->next = node; + else + firstChild = node; + + delete replaceThis; + node->parent = this; + return node; +} + + +bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) +{ + if ( removeThis->parent != this ) + { + assert( 0 ); + return false; + } + + if ( removeThis->next ) + removeThis->next->prev = removeThis->prev; + else + lastChild = removeThis->prev; + + if ( removeThis->prev ) + removeThis->prev->next = removeThis->next; + else + firstChild = removeThis->next; + + delete removeThis; + return true; +} + +const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = firstChild; node; node = node->next ) + { + if ( node->SValue() == TIXML_STRING( _value )) + return node; + } + return 0; +} + + +TiXmlNode* TiXmlNode::FirstChild( const char * _value ) +{ + TiXmlNode* node; + for ( node = firstChild; node; node = node->next ) + { + if ( node->SValue() == TIXML_STRING( _value )) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = lastChild; node; node = node->prev ) + { + if ( node->SValue() == TIXML_STRING (_value)) + return node; + } + return 0; +} + +TiXmlNode* TiXmlNode::LastChild( const char * _value ) +{ + TiXmlNode* node; + for ( node = lastChild; node; node = node->prev ) + { + if ( node->SValue() == TIXML_STRING (_value)) + return node; + } + return 0; +} + +const TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild(); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling(); + } +} + +TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous ) +{ + if ( !previous ) + { + return FirstChild(); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling(); + } +} + +const TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild( val ); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling( val ); + } +} + +TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous ) +{ + if ( !previous ) + { + return FirstChild( val ); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling( val ); + } +} + +const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = next; node; node = node->next ) + { + if ( node->SValue() == TIXML_STRING (_value)) + return node; + } + return 0; +} + +TiXmlNode* TiXmlNode::NextSibling( const char * _value ) +{ + TiXmlNode* node; + for ( node = next; node; node = node->next ) + { + if ( node->SValue() == TIXML_STRING (_value)) + return node; + } + return 0; +} + +const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = prev; node; node = node->prev ) + { + if ( node->SValue() == TIXML_STRING (_value)) + return node; + } + return 0; +} + +TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) +{ + TiXmlNode* node; + for ( node = prev; node; node = node->prev ) + { + if ( node->SValue() == TIXML_STRING (_value)) + return node; + } + return 0; +} + +void TiXmlElement::RemoveAttribute( const char * name ) +{ + TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + { + attributeSet.Remove( node ); + delete node; + } +} + +const TiXmlElement* TiXmlNode::FirstChildElement() const +{ + const TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + +TiXmlElement* TiXmlNode::FirstChildElement() +{ + TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + +const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = FirstChild( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + +TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) +{ + TiXmlNode* node; + + for ( node = FirstChild( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + +const TiXmlElement* TiXmlNode::NextSiblingElement() const +{ + const TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + +TiXmlElement* TiXmlNode::NextSiblingElement() +{ + TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + +const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = NextSibling( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + +TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) +{ + TiXmlNode* node; + + for ( node = NextSibling( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlDocument* TiXmlNode::GetDocument() const +{ + const TiXmlNode* node; + + for( node = this; node; node = node->parent ) + { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; +} + +TiXmlDocument* TiXmlNode::GetDocument() +{ + TiXmlNode* node; + + for( node = this; node; node = node->parent ) + { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; +} + +TiXmlElement::TiXmlElement (const char * _value) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} + + +#ifdef TIXML_USE_STL +TiXmlElement::TiXmlElement( const std::string& _value ) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} +#endif + + +TiXmlElement::TiXmlElement( const TiXmlElement& copy) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + copy.CopyTo( this ); +} + + +void TiXmlElement::operator=( const TiXmlElement& base ) +{ + ClearThis(); + base.CopyTo( this ); +} + + +TiXmlElement::~TiXmlElement() +{ + ClearThis(); +} + + +void TiXmlElement::ClearThis() +{ + Clear(); + while( attributeSet.First() ) + { + TiXmlAttribute* node = attributeSet.First(); + attributeSet.Remove( node ); + delete node; + } +} + + +const char * TiXmlElement::Attribute( const char * name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + + if ( node ) + return node->Value(); + + return 0; +} + + +const char * TiXmlElement::Attribute( const char * name, int* i ) const +{ + const char * s = Attribute( name ); + if ( i ) + { + if ( s ) + *i = atoi( s ); + else + *i = 0; + } + return s; +} + + +const char * TiXmlElement::Attribute( const char * name, double* d ) const +{ + const char * s = Attribute( name ); + if ( d ) + { + if ( s ) + *d = atof( s ); + else + *d = 0; + } + return s; +} + + +int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + return node->QueryIntValue( ival ); +} + + +int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + return node->QueryDoubleValue( dval ); +} + + +void TiXmlElement::SetAttribute( const char * name, int val ) +{ + char buf[64]; + sprintf( buf, "%d", val ); + SetAttribute( name, buf ); +} + + +void TiXmlElement::SetDoubleAttribute( const char * name, double val ) +{ + char buf[64]; + std::stringstream sst; + sst.imbue(std::locale::classic()); + sst << std::fixed; + sst << std::showpoint; + sst << std::setprecision(6); + sst << val; + strncpy( buf, sst.str().c_str(), 63 ); + SetAttribute( name, buf); +} + + +void TiXmlElement::SetAttribute( const char * name, const char * _value ) +{ + TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + { + node->SetValue( _value ); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); + if ( attrib ) + { + attributeSet.Add( attrib ); + } + else + { + TiXmlDocument* document = GetDocument(); + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); + } +} + +void TiXmlElement::Print( TIXML_OSTREAM& cfile, int depth ) const +{ + int i; + for ( i=0; iNext() ) + { + cfile << ' '; + attrib->Print( cfile, depth ); + } + + // There are 3 different formatting approaches: + // 1) An element without children is printed as a node + // 2) An element with only a text child is printed as text + // 3) An element with children is printed on multiple lines. + TiXmlNode* node; + if ( !firstChild ) + { + cfile << " />"; + } + else if ( firstChild == lastChild && firstChild->ToText() ) + { + cfile << '>'; + firstChild->Print( cfile, depth + 1 ); + cfile << "'; + } + else + { + cfile << '>'; + + for ( node = firstChild; node; node=node->NextSibling() ) + { + if ( !node->ToText() ) + { + cfile << '\n'; + } + node->Print( cfile, depth+1 ); + } + cfile << '\n'; + for( i=0; i'; + } +} + +void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const +{ + (*stream) << "<" << value; + + const TiXmlAttribute* attrib; + for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() ) + { + (*stream) << " "; + attrib->StreamOut( stream ); + } + + // If this node has children, give it a closing tag. Else + // make it an empty tag. + TiXmlNode* node; + if ( firstChild ) + { + (*stream) << ">"; + + for ( node = firstChild; node; node=node->NextSibling() ) + { + node->StreamOut( stream ); + } + (*stream) << ""; + } + else + { + (*stream) << " />"; + } +} + + +void TiXmlElement::CopyTo( TiXmlElement* target ) const +{ + // superclass: + TiXmlNode::CopyTo( target ); + + // Element class: + // Clone the attributes, then clone the children. + const TiXmlAttribute* attribute = 0; + for( attribute = attributeSet.First(); + attribute; + attribute = attribute->Next() ) + { + target->SetAttribute( attribute->Name(), attribute->Value() ); + } + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + + +TiXmlNode* TiXmlElement::Clone() const +{ + TiXmlElement* clone = new TiXmlElement( Value() ); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + ClearError(); +} + +TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + value = documentName; + ClearError(); +} + + +#ifdef TIXML_USE_STL +TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + value = documentName; + ClearError(); +} +#endif + + +TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDocument::operator=( const TiXmlDocument& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) +{ +#ifdef TIXML_USE_STL + return LoadFile(fs::u8path(value), encoding); +#else + // See STL_STRING_BUG below. + StringToBuffer buf( value ); + + if ( buf.buffer && LoadFile( buf.buffer, encoding ) ) + return true; + + return false; +#endif +} + + +bool TiXmlDocument::SaveFile() const +{ +#ifdef TIXML_USE_STL + return SaveFile(fs::u8path(value)); +#else + // See STL_STRING_BUG below. + StringToBuffer buf( value ); + + if ( buf.buffer && SaveFile( buf.buffer ) ) + return true; + + return false; +#endif +} + +#ifndef TIXML_USE_STL +bool TiXmlDocument::LoadFile( const char* filename, TiXmlEncoding encoding ) +{ + // Delete the existing data: + Clear(); + location.Clear(); + + // There was a really terrifying little bug here. The code: + // value = filename + // in the STL case, cause the assignment method of the std::string to + // be called. What is strange, is that the std::string had the same + // address as it's c_str() method, and so bad things happen. Looks + // like a bug in the Microsoft STL implementation. + // See STL_STRING_BUG above. + // Fixed with the StringToBuffer class. + value = filename; + + FILE* file = fopen( value.c_str (), "r" ); + + if ( file ) + { + // Get the file size, so we can pre-allocate the string. HUGE speed impact. + long length = 0; + fseek( file, 0, SEEK_END ); + length = ftell( file ); + fseek( file, 0, SEEK_SET ); + + // Strange case, but good to handle up front. + if ( length == 0 ) + { + fclose( file ); + return false; + } + + // If we have a file, assume it is all one big XML file, and read it in. + // The document parser may decide the document ends sooner than the entire file, however. + TIXML_STRING data; + data.reserve( length ); + + const int BUF_SIZE = 2048; + char buf[BUF_SIZE]; + + while( fgets( buf, BUF_SIZE, file ) ) + { + data += buf; + } + fclose( file ); + + Parse( data.c_str(), 0, encoding ); + + if ( Error() ) + return false; + else + return true; + } + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; +} + +bool TiXmlDocument::SaveFile( const char * filename ) const +{ + // The old c stuff lives on... + FILE* fp = fopen( filename, "w" ); + if ( fp ) + { + Print( fp, 0 ); + fclose( fp ); + return true; + } + return false; +} + +#else // !TIXML_USE_STL + +bool TiXmlDocument::LoadFile( const fs::path& filename, TiXmlEncoding encoding ) +{ + Clear(); + location.Clear(); + + value = filename.u8string(); + + std::error_code ec; + const auto length = fs::file_size(filename, ec); + if (ec || length == 0) + return false; + + std::unique_ptr data; + { + std::filebuf file; + if (file.open(filename, std::ios::binary | std::ios::in)) + { + data.reset(new char[length + 1]); + if (file.sgetn(data.get(), length) != length) + return false; + } + else + { + SetError(TIXML_ERROR_OPENING_FILE, nullptr, nullptr, TIXML_ENCODING_UNKNOWN); + return false; + } + } + data[length] = '\0'; + Parse(data.get(), nullptr, encoding); + return !Error(); +} + +bool TiXmlDocument::SaveFile( const fs::path& filename ) const +{ + if (std::ofstream stream{filename, std::ios::binary | std::ios::out | std::ios::trunc}) + { + Print(stream, 0); + return true; + } + return false; +} +#endif // TIXML_USE_STL + +void TiXmlDocument::CopyTo( TiXmlDocument* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->error = error; + target->errorDesc = errorDesc.c_str (); + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + + +TiXmlNode* TiXmlDocument::Clone() const +{ + TiXmlDocument* clone = new TiXmlDocument(); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlDocument::Print( TIXML_OSTREAM& cfile, int depth ) const +{ + const TiXmlNode* node; + for ( node=FirstChild(); node; node=node->NextSibling() ) + { + node->Print( cfile, depth ); + cfile << '\n'; + } +} + +void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const +{ + const TiXmlNode* node; + for ( node=FirstChild(); node; node=node->NextSibling() ) + { + node->StreamOut( out ); + + // Special rule for streams: stop after the root element. + // The stream in code will only read one element, so don't + // write more than one. + if ( node->ToElement() ) + break; + } +} + + +const TiXmlAttribute* TiXmlAttribute::Next() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} + +TiXmlAttribute* TiXmlAttribute::Next() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} + +const TiXmlAttribute* TiXmlAttribute::Previous() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} + +TiXmlAttribute* TiXmlAttribute::Previous() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} + +void TiXmlAttribute::Print( TIXML_OSTREAM& cfile, int /*depth*/ ) const +{ + TIXML_STRING n, v; + + PutString( name, &n ); + PutString( value, &v ); + + if (value.find ('\"') == TIXML_STRING::npos) + cfile << n << "=\"" << v << '"'; + else + cfile << n << "='" << v << '\''; +} + + +void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const +{ + if (value.find( '\"' ) != TIXML_STRING::npos) + { + PutString( name, stream ); + (*stream) << "=" << "'"; + PutString( value, stream ); + (*stream) << "'"; + } + else + { + PutString( name, stream ); + (*stream) << "=" << "\""; + PutString( value, stream ); + (*stream) << "\""; + } +} + +int TiXmlAttribute::QueryIntValue( int* ival ) const +{ + if ( sscanf( value.c_str(), "%d", ival ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +int TiXmlAttribute::QueryDoubleValue( double* dval ) const +{ + std::stringstream sst; + sst.imbue(std::locale::classic()); + sst << value.c_str(); + if ( sst >> *dval ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +void TiXmlAttribute::SetIntValue( int _value ) +{ + char buf [64]; + sprintf (buf, "%d", _value); + SetValue (buf); +} + +void TiXmlAttribute::SetDoubleValue( double _value ) +{ + char buf [64]; + std::stringstream sst; + sst.imbue(std::locale::classic()); + sst << std::fixed; + sst << std::showpoint; + sst << std::setprecision(6); + sst << _value; + strncpy( buf, sst.str().c_str(), 63 ); + SetValue (buf); +} + +int TiXmlAttribute::IntValue() const +{ + return atoi (value.c_str ()); +} + +double TiXmlAttribute::DoubleValue() const +{ + return atof (value.c_str ()); +} + + +TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlComment::operator=( const TiXmlComment& base ) +{ + Clear(); + base.CopyTo( this ); +} + + +void TiXmlComment::Print( TIXML_OSTREAM& cfile, int depth ) const +{ + for ( int i=0; i"; +} + +void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const +{ + (*stream) << ""; +} + + +void TiXmlComment::CopyTo( TiXmlComment* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +TiXmlNode* TiXmlComment::Clone() const +{ + TiXmlComment* clone = new TiXmlComment(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlText::Print( TIXML_OSTREAM& cfile, int /*depth*/ ) const +{ + TIXML_STRING buffer; + PutString( value, &buffer ); + cfile << buffer; +} + + +void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const +{ + PutString( value, stream ); +} + + +void TiXmlText::CopyTo( TiXmlText* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +TiXmlNode* TiXmlText::Clone() const +{ + TiXmlText* clone = 0; + clone = new TiXmlText( "" ); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlDeclaration::TiXmlDeclaration( const char * _version, + const char * _encoding, + const char * _standalone ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} + + +#ifdef TIXML_USE_STL +TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} +#endif + + +TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::Print( TIXML_OSTREAM& cfile, int /*depth*/ ) const +{ + cfile << ""; +} + +void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const +{ + (*stream) << ""; +} + + +void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->version = version; + target->encoding = encoding; + target->standalone = standalone; +} + + +TiXmlNode* TiXmlDeclaration::Clone() const +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlUnknown::Print( TIXML_OSTREAM& cfile, int depth ) const +{ + for ( int i=0; i'; +} + + +void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const +{ + (*stream) << "<" << value << ">"; // Don't use entities here! It is unknown. +} + + +void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +TiXmlNode* TiXmlUnknown::Clone() const +{ + TiXmlUnknown* clone = new TiXmlUnknown(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlAttributeSet::TiXmlAttributeSet() +{ + sentinel.next = &sentinel; + sentinel.prev = &sentinel; +} + + +TiXmlAttributeSet::~TiXmlAttributeSet() +{ + assert( sentinel.next == &sentinel ); + assert( sentinel.prev == &sentinel ); +} + + +void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) +{ + assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. + + addMe->next = &sentinel; + addMe->prev = sentinel.prev; + + sentinel.prev->next = addMe; + sentinel.prev = addMe; +} + +void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) +{ + TiXmlAttribute* node; + + for( node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node == removeMe ) + { + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = 0; + node->prev = 0; + return; + } + } + assert( 0 ); // we tried to remove a non-linked attribute. +} + +const TiXmlAttribute* TiXmlAttributeSet::Find( const char * name ) const +{ + const TiXmlAttribute* node; + + for( node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} + +TiXmlAttribute* TiXmlAttributeSet::Find( const char * name ) +{ + TiXmlAttribute* node; + + for( node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} + +#ifdef TIXML_USE_STL +TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base) +{ + TIXML_STRING tag; + tag.reserve( 8 * 1000 ); + base.StreamIn( &in, &tag ); + + base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); + return in; +} +#endif + + +TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base) +{ + base.StreamOut (& out); + return out; +} + + +#ifdef TIXML_USE_STL +std::string & operator<< (std::string& out, const TiXmlNode& base ) +{ + std::ostringstream os_stream( std::ostringstream::out ); + base.StreamOut( &os_stream ); + + out.append( os_stream.str() ); + return out; +} +#endif + + +TiXmlHandle TiXmlHandle::FirstChild() const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement() const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild(); + for ( i=0; + child && iNextSibling(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild( value ); + for ( i=0; + child && iNextSibling( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement(); + for ( i=0; + child && iNextSiblingElement(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement( value ); + for ( i=0; + child && iNextSiblingElement( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} diff --git a/libs/tinyxml/src/tinyxmlerror.cpp b/libs/tinyxml/src/tinyxmlerror.cpp new file mode 100644 index 00000000000..46a29d1494c --- /dev/null +++ b/libs/tinyxml/src/tinyxmlerror.cpp @@ -0,0 +1,51 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "tinyxml/tinyxml.h" + +// The goal of the seperate error file is to make the first +// step towards localization. tinyxml (currently) only supports +// latin-1, but at least the error messages could now be translated. +// +// It also cleans up the code a bit. +// + +const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] = +{ + "No error", + "Error", + "Failed to open file", + "Memory allocation failed.", + "Error parsing Element.", + "Failed to read Element name", + "Error reading Element value.", + "Error reading Attributes.", + "Error: empty tag.", + "Error reading end tag.", + "Error parsing Unknown.", + "Error parsing Comment.", + "Error parsing Declaration.", + "Error document empty.", + "Error null (0) or unexpected EOF found in input stream.", +}; diff --git a/libs/tinyxml/src/tinyxmlparser.cpp b/libs/tinyxml/src/tinyxmlparser.cpp new file mode 100644 index 00000000000..29afe773399 --- /dev/null +++ b/libs/tinyxml/src/tinyxmlparser.cpp @@ -0,0 +1,1511 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "tinyxml/tinyxml.h" + +#include + +//#define DEBUG_PARSER + +#if defined( _DEBUG ) && defined( _MSC_VER ) +#include +#define TIXML_LOG OutputDebugString +#else +#define TIXML_LOG printf +#endif + +// Note tha "PutString" hardcodes the same list. This +// is less flexible than it appears. Changing the entries +// or order will break putstring. +TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = +{ + { "&", 5, '&' }, + { "<", 4, '<' }, + { ">", 4, '>' }, + { """, 6, '\"' }, + { "'", 6, '\'' } +}; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// Including the basic of this table, which determines the #bytes in the +// sequence from the lead byte. 1 placed for invalid sequences -- +// although the result will be junk, pass it through as much as possible. +// Beware of the non-characters in UTF-8: +// ef bb bf (Microsoft "lead bytes") +// ef bf be +// ef bf bf + +const char TIXML_UTF_LEAD_0 = (const char)0xef; +const char TIXML_UTF_LEAD_1 = (const char)0xbb; +const char TIXML_UTF_LEAD_2 = (const char)0xbf; + +const int TiXmlBase::utf8ByteTable[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte + 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid +}; + + +void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) + *length = 1; + else if ( input < 0x800 ) + *length = 2; + else if ( input < 0x10000 ) + *length = 3; + else if ( input < 0x200000 ) + *length = 4; + else + { *length = 0; return; } // This code won't covert this correctly anyway. + + output += *length; + + // Scary scary fall throughs. + switch (*length) + { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + } +} + + +/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalpha( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalpha( anyByte ); +// } +} + + +/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalnum( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalnum( anyByte ); +// } +} + + +class TiXmlParsingData +{ + friend class TiXmlDocument; + public: + void Stamp( const char* now, TiXmlEncoding encoding ); + + const TiXmlCursor& Cursor() { return cursor; } + + private: + // Only used by the document! + TiXmlParsingData( const char* start, int _tabsize, int row, int col ) + { + assert( start ); + stamp = start; + tabsize = _tabsize; + cursor.row = row; + cursor.col = col; + } + + TiXmlCursor cursor; + const char* stamp; + int tabsize; +}; + + +void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) +{ + assert( now ); + + // Do nothing if the tabsize is 0. + if ( tabsize < 1 ) + { + return; + } + + // Get the current row, column. + int row = cursor.row; + int col = cursor.col; + const char* p = stamp; + assert( p ); + + while ( p < now ) + { + // Code contributed by Fletcher Dunn: (modified by lee) + switch (*p) { + case 0: + // We *should* never get here, but in case we do, don't + // advance past the terminating null character, ever + return; + + case '\r': + // bump down to the next line + ++row; + col = 0; + // Eat the character + ++p; + + // Check for \r\n sequence, and treat this as a single character + if (*p == '\n') { + ++p; + } + break; + + case '\n': + // bump down to the next line + ++row; + col = 0; + + // Eat the character + ++p; + + // Check for \n\r sequence, and treat this as a single + // character. (Yes, this bizarre thing does occur still + // on some arcane platforms...) + if (*p == '\r') { + ++p; + } + break; + + case '\t': + // Eat the character + ++p; + + // Skip to next tab stop + col = (col / tabsize + 1) * tabsize; + break; + + case TIXML_UTF_LEAD_0: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( *(p+1) && *(p+2) ) + { + // In these cases, don't advance the column. These are + // 0-width spaces. + if ( *(p+1)==TIXML_UTF_LEAD_1 && *(p+2)==TIXML_UTF_LEAD_2 ) + p += 3; + else if ( *(p+1)==(char)(0xbf) && *(p+2)==(char)(0xbe) ) + p += 3; + else if ( *(p+1)==(char)(0xbf) && *(p+2)==(char)(0xbf) ) + p += 3; + else + { p +=3; ++col; } // A normal character. + } + } + else + { + ++p; + ++col; + } + break; + + default: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // Eat the 1 to 4 byte utf8 character. + int step = TiXmlBase::utf8ByteTable[*((unsigned char*)p)]; + if ( step == 0 ) + step = 1; // Error case from bad encoding, but handle gracefully. + p += step; + + // Just advance one column, of course. + ++col; + } + else + { + ++p; + ++col; + } + break; + } + } + cursor.row = row; + cursor.col = col; + assert( cursor.row >= -1 ); + assert( cursor.col >= -1 ); + stamp = p; + assert( stamp ); +} + + +const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) +{ + if ( !p || !*p ) + { + return 0; + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + while ( *p ) + { + // Skip the stupid Microsoft UTF-8 Byte order marks + if ( *(p+0)==TIXML_UTF_LEAD_0 + && *(p+1)==TIXML_UTF_LEAD_1 + && *(p+2)==TIXML_UTF_LEAD_2 ) + { + p += 3; + continue; + } + else if(*(p+0)==TIXML_UTF_LEAD_0 + && *(p+1)==(const char) 0xbf + && *(p+2)==(const char) 0xbe ) + { + p += 3; + continue; + } + else if(*(p+0)==TIXML_UTF_LEAD_0 + && *(p+1)==(const char) 0xbf + && *(p+2)==(const char) 0xbf ) + { + p += 3; + continue; + } + + if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. + ++p; + else + break; + } + } + else + { + while ( *p && ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) ) + ++p; + } + + return p; +} + +#ifdef TIXML_USE_STL +/*static*/ bool TiXmlBase::StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag ) +{ + for( ;; ) + { + if ( !in->good() ) return false; + + int c = in->peek(); + // At this scope, we can't get to a document. So fail silently. + if ( !IsWhiteSpace( c ) || c <= 0 ) + return true; + + *tag += (char) in->get(); + } +} + +/*static*/ bool TiXmlBase::StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag ) +{ + //assert( character > 0 && character < 128 ); // else it won't work in utf-8 + while ( in->good() ) + { + int c = in->peek(); + if ( c == character ) + return true; + if ( c <= 0 ) // Silent failure: can't get document at this scope + return false; + + in->get(); + *tag += (char) c; + } + return false; +} +#endif + +const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) +{ + *name = ""; + assert( p ); + + // Names start with letters or underscores. + // Of course, in unicode, tinyxml has no idea what a letter *is*. The + // algorithm is generous. + // + // After that, they can be letters, underscores, numbers, + // hyphens, or colons. (Colons are valid ony for namespaces, + // but tinyxml can't tell namespaces from names.) + if ( p && *p + && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) + { + while( p && *p + && ( IsAlphaNum( (unsigned char ) *p, encoding ) + || *p == '_' + || *p == '-' + || *p == '.' + || *p == ':' ) ) + { + (*name) += *p; + ++p; + } + return p; + } + return 0; +} + +const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) +{ + // Presume an entity, and pull it out. + TIXML_STRING ent; + int i; + *length = 0; + + if ( *(p+1) && *(p+1) == '#' && *(p+2) ) + { + unsigned long ucs = 0; + //*ME: warning C4244: convert '__w64 int' to 'unsigned' + //*ME: Use size_t instead of unsigned (pointer-arithmetic) + size_t delta = 0; + unsigned mult = 1; + + if ( *(p+2) == 'x' ) + { + // Hexadecimal. + if ( !*(p+3) ) return 0; + + const char* q = p+3; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != 'x' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else if ( *q >= 'a' && *q <= 'f' ) + ucs += mult * (*q - 'a' + 10); + else if ( *q >= 'A' && *q <= 'F' ) + ucs += mult * (*q - 'A' + 10 ); + else + return 0; + mult *= 16; + --q; + } + } + else + { + // Decimal. + if ( !*(p+2) ) return 0; + + const char* q = p+2; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != '#' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else + return 0; + mult *= 10; + --q; + } + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + } + else + { + *value = (char)ucs; + *length = 1; + } + return p + delta + 1; + } + + // Now try to match it. + for( i=0; iappend( cArr, len ); + } + } + else + { + bool whitespace = false; + + // Remove leading white space: + p = SkipWhiteSpace( p, encoding ); + while ( p && *p + && !StringEqual( p, endTag, caseInsensitive, encoding ) ) + { + if ( *p == '\r' || *p == '\n' ) + { + whitespace = true; + ++p; + } + else if ( IsWhiteSpace( *p ) ) + { + whitespace = true; + ++p; + } + else + { + // If we've found whitespace, add it before the + // new character. Any whitespace just becomes a space. + if ( whitespace ) + { + (*text) += ' '; + whitespace = false; + } + int len; + char cArr[4] = { 0, 0, 0, 0 }; + p = GetChar( p, cArr, &len, encoding ); + if ( len == 1 ) + (*text) += cArr[0]; // more efficient + else + text->append( cArr, len ); + } + } + } + return p + strlen( endTag ); +} + +#ifdef TIXML_USE_STL + +void TiXmlDocument::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) +{ + // The basic issue with a document is that we don't know what we're + // streaming. Read something presumed to be a tag (and hope), then + // identify it, and call the appropriate stream method on the tag. + // + // This "pre-streaming" will never read the closing ">" so the + // sub-tag can orient itself. + + if ( !StreamTo( in, '<', tag ) ) + { + SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + while ( in->good() ) + { + int tagIndex = (int) tag->length(); + while ( in->good() && in->peek() != '>' ) + { + int c = in->get(); + if ( c <= 0 ) + { + SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + break; + } + (*tag) += (char) c; + } + + if ( in->good() ) + { + // We now have something we presume to be a node of + // some sort. Identify it, and call the node to + // continue streaming. + TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); + + if ( node ) + { + node->StreamIn( in, tag ); + bool isElement = node->ToElement() != 0; + delete node; + node = 0; + + // If this is the root element, we're done. Parsing will be + // done by the >> operator. + if ( isElement ) + { + return; + } + } + else + { + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + } + } + // We should have returned sooner. + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); +} + +#endif + +const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) +{ + ClearError(); + + // Parse away, at the document level. Since a document + // contains nothing but other tags, most of what happens + // here is skipping white space. + if ( !p || !*p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + // Note that, for a document, this needs to come + // before the while space skip, so that parsing + // starts from the pointer we are given. + location.Clear(); + if ( prevData ) + { + location.row = prevData->cursor.row; + location.col = prevData->cursor.col; + } + else + { + location.row = 0; + location.col = 0; + } + TiXmlParsingData data( p, TabSize(), location.row, location.col ); + location = data.Cursor(); + + if ( encoding == TIXML_ENCODING_UNKNOWN ) + { + // Check for the Microsoft UTF-8 lead bytes. + if ( *(p+0) && *(p+0) == TIXML_UTF_LEAD_0 + && *(p+1) && *(p+1) == TIXML_UTF_LEAD_1 + && *(p+2) && *(p+2) == TIXML_UTF_LEAD_2 ) + { + encoding = TIXML_ENCODING_UTF8; + } + } + + p = SkipWhiteSpace( p, encoding ); + if ( !p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + while ( p && *p ) + { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) + { + p = node->Parse( p, &data, encoding ); + LinkEndChild( node ); + } + else + { + break; + } + + // Did we get encoding info? + if ( encoding == TIXML_ENCODING_UNKNOWN + && node->ToDeclaration() ) + { + TiXmlDeclaration* dec = node->ToDeclaration(); + const char* enc = dec->Encoding(); + assert( enc ); + + if ( *enc == 0 ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice + else + encoding = TIXML_ENCODING_LEGACY; + } + + p = SkipWhiteSpace( p, encoding ); + } + + // Was this empty? + if ( !firstChild ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); + return 0; + } + + // All is well. + return p; +} + +void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + // The first error in a chain is more accurate - don't set again! + if ( error ) + return; + + assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); + error = true; + errorId = err; + errorDesc = errorString[ errorId ]; + + errorLocation.Clear(); + if ( pError && data ) + { + //TiXmlParsingData data( pError, prevData ); + data->Stamp( pError, encoding ); + errorLocation = data->Cursor(); + } +} + + +TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) +{ + TiXmlNode* returnNode = 0; + + p = SkipWhiteSpace( p, encoding ); + if( !p || !*p || *p != '<' ) + { + return 0; + } + + TiXmlDocument* doc = GetDocument(); + p = SkipWhiteSpace( p, encoding ); + + if ( !p || !*p ) + { + return 0; + } + + // What is this thing? + // - Elements start with a letter or underscore, but xml is reserved. + // - Comments: "; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + p = ReadText( p, &value, false, endTag, false, encoding ); + return p; +} + + +const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) return 0; + + int tabsize = 4; + if ( document ) + tabsize = document->TabSize(); + +// TiXmlParsingData data( p, prevData ); + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + // Read the name, the '=' and the value. + const char* pErr = p; + p = ReadName( p, &name, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p || *p != '=' ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + ++p; // skip '=' + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + const char* end; + + if ( *p == '\'' ) + { + ++p; + end = "\'"; + p = ReadText( p, &value, false, end, false, encoding ); + } + else if ( *p == '"' ) + { + ++p; + end = "\""; + p = ReadText( p, &value, false, end, false, encoding ); + } + else + { + // All attribute values should be in single or double quotes. + // But this is such a common error that the parser will try + // its best, even without them. + value = ""; + while ( p && *p // existence + && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace + && *p != '/' && *p != '>' ) // tag end + { + value += *p; + ++p; + } + } + return p; +} + +#ifdef TIXML_USE_STL +void TiXmlText::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->peek(); + if ( c == '<' ) + return; + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + (*tag) += (char) c; + in->get(); + } +} +#endif + +const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + value = ""; +// TiXmlParsingData data( p, prevData ); + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + bool ignoreWhite = true; + + const char* end = "<"; + p = ReadText( p, &value, ignoreWhite, end, false, encoding ); + if ( p ) + return p-1; // don't truncate the '<' + return 0; +} + +#ifdef TIXML_USE_STL +void TiXmlDeclaration::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c; + + if ( c == '>' ) + { + // All is well. + return; + } + } +} +#endif + +const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) +{ + p = SkipWhiteSpace( p, _encoding ); + // Find the beginning, find the end, and look for + // the stuff in-between. + TiXmlDocument* document = GetDocument(); + if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); + return 0; + } +// TiXmlParsingData data( p, prevData ); + if ( data ) + { + data->Stamp( p, _encoding ); + location = data->Cursor(); + } + p += 5; + + version = ""; + encoding = ""; + standalone = ""; + + while ( p && *p ) + { + if ( *p == '>' ) + { + ++p; + return p; + } + + p = SkipWhiteSpace( p, _encoding ); + if ( StringEqual( p, "version", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + version = attrib.Value(); + } + else if ( StringEqual( p, "encoding", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + encoding = attrib.Value(); + } + else if ( StringEqual( p, "standalone", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + standalone = attrib.Value(); + } + else + { + // Read over whatever it is. + while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) + ++p; + } + } + return 0; +} + +bool TiXmlText::Blank() const +{ + for ( unsigned i=0; i @@ -32,7 +32,7 @@ analogy lead you astray, especially in your optimism for how much we have implem But if we want to replace a collection of sliders and modify several features we don't want to have to repeat all the configuration. Instead we define a user component class. This class has a name and a parent class but also advertises properties. Much like CSS these properties cascade - so a control can override them, or a user class can have a user class as a parent. Here we take + so a control can ovveride them, or a user class can have a user class as a parent. Here we take the simplest approach though of just defining a new slider class which we intend to use for the LFO H Sliders. We share the parent, CSurgeSlider, and modify the handle_image and the handle_tray (backdrop) with a custom image. @@ -64,7 +64,7 @@ analogy lead you astray, especially in your optimism for how much we have implem diff --git a/scripts/installer_linux/make_rpm.sh b/scripts/installer_linux/make_rpm.sh index b7825ab0b51..ea9327d926b 100755 --- a/scripts/installer_linux/make_rpm.sh +++ b/scripts/installer_linux/make_rpm.sh @@ -60,7 +60,7 @@ pushd ./installer-tmp # Name of Package PACKAGE_NAME=surge-xt -# Date in RFC format for the Changelog +# Date in RFC formate for the Changelog DATE_RFC=`date --rfc-email` # Date in Day-of-Week Month Day Year format for the rpm config header. DATE_RPM=`date` diff --git a/scripts/ipy/Demonstrate Surge in Python.ipynb b/scripts/ipy/Demonstrate Surge in Python.ipynb index e0167a44a8f..52bd6068d09 100644 --- a/scripts/ipy/Demonstrate Surge in Python.ipynb +++ b/scripts/ipy/Demonstrate Surge in Python.ipynb @@ -13,7 +13,7 @@ "This document assumes that\n", "1. You basically understand how Surge works as a synth. Concepts like\n", " scenes, oscilaltors, modulators etc\n", - "2. You can build surge from source successfully as outlined in the README and\n", + "2. You can build surge from source succesfully as outlined in the README and\n", "3. You can manage a python environment with custom modules\n", "4. You are running on a machine where the Surge synth is installed (namely\n", " the factory data directory is present in an OS specific places as described\n", @@ -375,7 +375,7 @@ "metadata": {}, "source": [ "Finally, lets define a function which plays surge for about 4 seconds, with\n", - "a key release at second 3, and returns a smoothed RMS of the output. At this point\n", + "a key relese at second 3, and returns a smoothed RMS of the output. At this point\n", "it should be clear how to do that." ] }, diff --git a/scripts/pyauto-tests/basics-about-screen.py b/scripts/pyauto-tests/basics-about-screen.py index a3371cca295..18022ee2963 100644 --- a/scripts/pyauto-tests/basics-about-screen.py +++ b/scripts/pyauto-tests/basics-about-screen.py @@ -1,5 +1,5 @@ # The simplest use of the accessibility API. Grab a surge xt running instance -# and dump the accessibility hierarchy +# and dump the accesibility heirarchy import atomacos diff --git a/scripts/pyauto-tests/basics-show-open-menu.py b/scripts/pyauto-tests/basics-show-open-menu.py index 11b3c3f083d..f9d4f2a3093 100644 --- a/scripts/pyauto-tests/basics-show-open-menu.py +++ b/scripts/pyauto-tests/basics-show-open-menu.py @@ -1,5 +1,5 @@ # The simplest use of the accessibility API. Grab a surge xt running instance -# and dump the accessibility hierarchy +# and dump the accesibility heirarchy import atomacos diff --git a/scripts/pyauto-tests/basics-show-tree.py b/scripts/pyauto-tests/basics-show-tree.py index c06e27bfc62..1613fe805af 100644 --- a/scripts/pyauto-tests/basics-show-tree.py +++ b/scripts/pyauto-tests/basics-show-tree.py @@ -1,5 +1,5 @@ # The simplest use of the accessibility API. Grab a surge xt running instance -# and dump the accessibility hierarchy +# and dump the accesibility heirarchy import atomacos diff --git a/scripts/pyauto-tests/mod-use-menu-buttons.py b/scripts/pyauto-tests/mod-use-menu-buttons.py index 0ec15140178..ddb8edb7bd0 100644 --- a/scripts/pyauto-tests/mod-use-menu-buttons.py +++ b/scripts/pyauto-tests/mod-use-menu-buttons.py @@ -1,4 +1,4 @@ -# Show that that the modulation menu properly exposes to accessibility +# Show that that the modulation menu properly exposes to accesibility # by dumping the menu, muting it, then dumping it again and unmuting it import sxttest diff --git a/scripts/win/build-win.ps1 b/scripts/win/build-win.ps1 index d5129fb75ec..23a22a4aeac 100644 --- a/scripts/win/build-win.ps1 +++ b/scripts/win/build-win.ps1 @@ -28,17 +28,17 @@ build-win.ps1 is a powershell script to control builds and do installs. It takes -cleanall Clean builds and remove visual studio files -build Build -install Install vst2 and 3. Will prompt for permissions - -bi build + install + -bi buid + install -cb clean + build -cbi clean + build + install -w32 Build 32 bit -It does not run premake yet. +It does not run premake yet. You need to onetime do - Set-ExecutionPolicy -scope CurrentUser RemoteSigned + Set-ExecutionPolicy -scope CurrentUser RemoteSigned to use this. "@ diff --git a/scripts/wt-tool/generated-wt.py b/scripts/wt-tool/generated-wt.py index 3f281e23955..ce52576d8b0 100644 --- a/scripts/wt-tool/generated-wt.py +++ b/scripts/wt-tool/generated-wt.py @@ -59,7 +59,7 @@ def npftoi15bin(fsamples): def generatewt(filename, genf, res, tables): """Given res as a function of npline,int -> npline to generate the nth table, - generate the wt file""" + genereate the wt file""" line = np.linspace(0, 1, res, endpoint=False) dat = [] for i in range(tables): @@ -76,7 +76,7 @@ def comparewt(fn1, fn2): l2 = np.linspace(0, 1, len(d2[0]), endpoint=False) if(len(d1) != len(d2)): - print(" Lengths don't match", len(d1), " ", len(d2)) + print(" Lenghts don't match", len(d1), " ", len(d2)) return for i in range(len(d1)): diff --git a/scripts/wt-tool/wt-tool.py b/scripts/wt-tool/wt-tool.py index 1fd9e14c989..cee8d1bf461 100755 --- a/scripts/wt-tool/wt-tool.py +++ b/scripts/wt-tool/wt-tool.py @@ -193,7 +193,7 @@ def main(): parser.add_option("-f", "--file", dest="file", help="wt_file being inspected or created", metavar="FILE") parser.add_option("-d", "--wav_dir", dest="wav_dir", - help="Directory containing or receiving wav files for wt", metavar="DIR") + help="Directory containing or recieving wav files for wt", metavar="DIR") parser.add_option("-n", "--normalize", dest="normalize", default="none", metavar="MODE", help="""(Create only) how to normalize input. Modes are 'none' leave input untouched; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dde923ad6fa..bc36a2d2f4e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,7 +13,6 @@ include(cmake/lib.cmake) message(STATUS "Using JUCE from ${SURGE_JUCE_PATH}") add_subdirectory(${SURGE_JUCE_PATH} ${CMAKE_BINARY_DIR}/JUCE EXCLUDE_FROM_ALL) -add_subdirectory(../libs/clap-juce-extensions clap-extensions EXCLUDE_FROM_ALL) add_library(simde INTERFACE) target_include_directories(simde INTERFACE ${CMAKE_SOURCE_DIR}/libs/simde) @@ -47,6 +46,10 @@ target_compile_definitions(surge-juce INTERFACE set(SURGE_JUCE_FORMATS VST3) +if (CLAP_JUCE_EXTENSIONS_ROOT) + add_subdirectory(${CLAP_JUCE_EXTENSIONS_ROOT} clap-extensions) +endif() + if(NOT SURGE_SKIP_STANDALONE) list(APPEND SURGE_JUCE_FORMATS Standalone) endif() diff --git a/src/cmake/lib.cmake b/src/cmake/lib.cmake index 052a0699886..0e0cbda8c87 100644 --- a/src/cmake/lib.cmake +++ b/src/cmake/lib.cmake @@ -86,19 +86,9 @@ function(surge_make_installers) if(APPLE) run_installer_script(installer_mac/make_installer.sh) - add_custom_command(TARGET surge-xt-distribution - POST_BUILD - WORKING_DIRECTORY ${SURGE_PRODUCT_DIR} - COMMAND zip -r ${SURGE_XT_DIST_OUTPUT_DIR}/surge-xt-macos-${SXTVER}-pluginsonly.zip . - ) elseif(UNIX) run_installer_script(installer_linux/make_deb.sh) run_installer_script(installer_linux/make_rpm.sh) - add_custom_command(TARGET surge-xt-distribution - POST_BUILD - WORKING_DIRECTORY ${SURGE_PRODUCT_DIR} - COMMAND tar cvzf ${SURGE_XT_DIST_OUTPUT_DIR}/surge-xt-linux-${SXTVER}-pluginsonly.tar.gz . - ) elseif(WIN32) add_custom_command(TARGET surge-xt-distribution POST_BUILD diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 8bf693d9a00..083ebb1e9d1 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -3,8 +3,10 @@ project(surge-common) surge_add_lib_subdirectory(airwindows) surge_add_lib_subdirectory(eurorack) +surge_add_lib_subdirectory(filesystem) surge_add_lib_subdirectory(fmt) surge_add_lib_subdirectory(strnatcmp) +surge_add_lib_subdirectory(tinyxml) surge_add_lib_subdirectory(oddsound-mts) if(MINGW) set(HAVE_VISIBILITY 0 CACHE INTERNAL "Force-disable libsamplerate's visibility check on MinGW") @@ -14,9 +16,6 @@ surge_add_lib_subdirectory(tuning-library) surge_add_lib_subdirectory(sqlite-3.23.3) surge_add_lib_subdirectory(LuaJitLib) -surge_add_lib_subdirectory(sst/sst-cpputils) -surge_add_lib_subdirectory(sst/sst-plugininfra) - set(PEGTL_BUILD_TESTS OFF CACHE BOOL "") set(PEGTL_BUILD_EXAMPLES OFF CACHE BOOL "") surge_add_lib_subdirectory(PEGTL) @@ -314,21 +313,17 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_BINARY_DIR}/geninclude/version.cp add_library(surge::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) target_link_libraries(${PROJECT_NAME} - PUBLIC +PUBLIC fmt luajit-5.1 samplerate surge::airwindows surge::eurorack - - sst-cpputils - sst-plugininfra - sst-plugininfra::filesystem - sst-plugininfra::tinyxml - + surge::filesystem surge::oddsound-mts surge::sqlite surge::strnatcmp + surge::tinyxml surge-common-binary tuning-library PRIVATE @@ -336,7 +331,7 @@ target_link_libraries(${PROJECT_NAME} surge-platform surge-juce taocpp::pegtl - PRIVATE +PRIVATE juce::juce_dsp ) diff --git a/src/common/DebugHelpers.h b/src/common/DebugHelpers.h index c5aa18a2c13..cc4957de4bf 100644 --- a/src/common/DebugHelpers.h +++ b/src/common/DebugHelpers.h @@ -1,7 +1,7 @@ /* ** DebugHelpers.h ** -** Contains debug APIs. Do not use them in production code. +** Cotnains debug APIs. Do not use them in production code. ** Pull requests with references to these functions will not be merged! ** */ diff --git a/src/common/FilterConfiguration.h b/src/common/FilterConfiguration.h index 45e9953b958..5c3f0b33cee 100644 --- a/src/common/FilterConfiguration.h +++ b/src/common/FilterConfiguration.h @@ -44,7 +44,7 @@ * right choice, but when you curse me for the odd name list, you can come back and read this * comment and feel slightly better. Finally, items which split and changed meaning got a new name * (so fut_comb is now fut_comb_pos and fut_comb_neg, say), which requires us to go and fix up any - * code which referred to the old values. + * code which refered to the old values. */ enum fu_type_sv14 diff --git a/src/common/LuaSupport.h b/src/common/LuaSupport.h index b5d861ff87b..caeb3f74380 100644 --- a/src/common/LuaSupport.h +++ b/src/common/LuaSupport.h @@ -58,7 +58,7 @@ bool parseStringDefiningFunction(lua_State *s, const std::string &definition, * top of the stack, bar next and hootie third. * * Return an integer which is the number of the functions which were resolved and - * the number which were nil. If the function returns 0 errorMessage will be populated + * the number which were nil. If the function returns 0 errorMessage will be popuplated * with something. */ int parseStringDefiningMultipleFunctions(lua_State *s, const std::string &definition, diff --git a/src/common/Parameter.cpp b/src/common/Parameter.cpp index a0c5e739916..ffa59a43b4a 100644 --- a/src/common/Parameter.cpp +++ b/src/common/Parameter.cpp @@ -361,7 +361,6 @@ bool Parameter::has_deformoptions() const { switch (ctrltype) { - case ct_freq_hpf: case ct_lfodeform: case ct_modern_trimix: case ct_alias_mask: @@ -2554,7 +2553,7 @@ void Parameter::get_display_of_modulation_depth(char *txt, float modulationDepth return; } float mf = modulationDepth; - // OK so this is already handed to us extended and this one is weird so + // OK so this is already handed to us extended and this one is wierd so auto qq = mf; if (extend_range) { diff --git a/src/common/Parameter.h b/src/common/Parameter.h index e411cca1f20..1f08f8482c8 100644 --- a/src/common/Parameter.h +++ b/src/common/Parameter.h @@ -266,7 +266,7 @@ struct ParameterDynamicDeactivationFunction : public ParameterDynamicBoolFunctio /* ** It used to be parameters were assigned IDs in SurgePatch using an int which we ++ed along the -** way. If we want to 'add at the end' but 'cluster together' we need a different data structure +** way. If we want to 'add at the end' but 'cluster together' we need a different data strcture ** to allow clusters of parameters, so instead make SurgePatch use a linked list (or multiple lists) ** while constructing params and then resolve them all at the end. This little class lets us ** do that. @@ -447,7 +447,7 @@ class Parameter pdata val{}, val_default{}, val_min{}, val_max{}; // You might be tempted to use a non-fixed-size member here, like a std::string, but - // this class gets pre-c++ memcopied so that's not an option which is why I do this wonky + // this class gets pre-c++ memcopied so thats not an option which is why I do this wonky // pointer thing and strncpy from a string onto ui_identifier ParameterIDCounter::promise_ptr_t id_promise{}; int id{}; diff --git a/src/common/PatchDB.cpp b/src/common/PatchDB.cpp index 13574c73ec4..bd430430869 100644 --- a/src/common/PatchDB.cpp +++ b/src/common/PatchDB.cpp @@ -225,7 +225,7 @@ struct TxnGuard struct PatchDB::WriterWorker { - static constexpr const char *schema_version = "11"; // I will rebuild if this is not my version + static constexpr const char *schema_version = "11"; // I will rebuild if this is not my verion // language=SQL static constexpr const char *setup_sql = R"SQL( @@ -356,7 +356,7 @@ CREATE TABLE IF NOT EXISTS Favorites ( if (ec != SQLITE_OK) { std::ostringstream oss; - oss << "An error occurred opening sqlite file '" << dbname << "'. The error was '" + oss << "An error occured opening sqlite file '" << dbname << "'. The error was '" << sqlite3_errmsg(dbh) << "'."; storage->reportError(oss.str(), "Surge Patch Database Error"); if (dbh) @@ -495,7 +495,7 @@ CREATE TABLE IF NOT EXISTS Favorites ( } } - // FIXME features should be an enum or something + // FIXME features shuld be an enum or something enum FeatureType { @@ -1030,7 +1030,7 @@ CREATE TABLE IF NOT EXISTS Favorites ( if (notifyOnError) { std::ostringstream oss; - oss << "An error occurred opening r/o sqlite file '" << dbname + oss << "An error occured opening r/o sqlite file '" << dbname << "'. The error was '" << sqlite3_errmsg(dbh) << "'."; storage->reportError(oss.str(), "Surge Patch Database Error"); } diff --git a/src/common/PatchDBQueryParser.cpp b/src/common/PatchDBQueryParser.cpp index a671bb724a1..8440176e9eb 100644 --- a/src/common/PatchDBQueryParser.cpp +++ b/src/common/PatchDBQueryParser.cpp @@ -31,7 +31,7 @@ namespace pegtl = tao::TAO_PEGTL_NAMESPACE; namespace grammar { -// CLang Format wants all these empty structs to be braced on newlines so turn it off for now +// CLang Format wants all these emtpy structs to be braced on newlines so turn it off for now // clang-format off struct expression; struct value; diff --git a/src/common/SkinModel.h b/src/common/SkinModel.h index e9c70291e26..d5c73a5c9c4 100644 --- a/src/common/SkinModel.h +++ b/src/common/SkinModel.h @@ -40,7 +40,7 @@ * and we want that default to be completely over-rideable in our VSTGUI * implementation. * - * And finally, we don't want the core of surge to reference VSTGUI. + * And finally, we don't want the core of surge to refernce VSTGUI. * * So that gets us the following set of collaborations * @@ -77,7 +77,7 @@ * 2. Have the data (but not the renderer) for the layout information in src/common * * I chose #2 mostly because #1 is especially tedious since a collection of parameters - * share a skin identity. For instance, all of the oscillator pitch sliders (of which there + * share a skin identity. For instance, all of the oscilator pitch sliders (of which there * are 6 as of 1.8.0) are a single point of skin identity. Thus attaching them to skin * data models in SurgePatch makes sense. * @@ -111,7 +111,7 @@ struct Component /* * We could have done something much clevere with templates and per-class enums * but decided not to. Instead here is an enum which is the union of all possible - * properties that an item can have. + * properites that an item can have. */ enum Properties { @@ -123,7 +123,7 @@ struct Component BACKGROUND, HOVER_IMAGE, HOVER_ON_IMAGE, - IMAGE, // Note for most components "image" binds to "background" but some have it separate + IMAGE, // Note for most components "image" binds to "background" but some have it seprate ROWS, COLUMNS, @@ -184,7 +184,7 @@ struct Component std::shared_ptr payload; /* - * To allow aliasing and backwards compatibility, a property binds to the skin engine + * To allow aliasing and backwards compatability, a property binds to the skin engine * with multiple names for a given class. */ Component &withProperty(Properties p, const std::initializer_list &names, diff --git a/src/common/SurgePatch.cpp b/src/common/SurgePatch.cpp index 8c81a35c142..31fd18f509e 100644 --- a/src/common/SurgePatch.cpp +++ b/src/common/SurgePatch.cpp @@ -531,18 +531,6 @@ SurgePatch::SurgePatch(SurgeStorage *storage) } } lfoPhaseName; - // Assign the dynamic deactivation handlers - static struct OscAudioInDeact : public ParameterDynamicDeactivationFunction - { - const bool getValue(const Parameter *p) const override - { - auto cge = p->ctrlgroup_entry; - auto osc = &(p->storage->getPatch().scene[p->scene - 1].osc[cge]); - - return osc->type.val.i == ot_audioinput; - } - } oscAudioInDeact; - static struct LfoRatePhaseDeact : public ParameterDynamicDeactivationFunction { const bool getValue(const Parameter *p) const override @@ -550,12 +538,8 @@ SurgePatch::SurgePatch(SurgeStorage *storage) auto cge = p->ctrlgroup_entry - ms_lfo1; auto lf = &(p->storage->getPatch().scene[p->scene - 1].lfo[cge]); auto res = lf->shape.val.i == lt_envelope; - if (!res && p->can_deactivate()) - { return p->deactivated; - } - return res; } } lfoRatePhaseDeact; @@ -567,30 +551,18 @@ SurgePatch::SurgePatch(SurgeStorage *storage) auto cge = p->ctrlgroup_entry - ms_lfo1; auto lf = &(p->storage->getPatch().scene[p->scene - 1].lfo[cge]); auto res = lf->delay.deactivated; - return res; } - Parameter *getPrimaryDeactivationDriver(const Parameter *p) const override { auto cge = p->ctrlgroup_entry - ms_lfo1; auto lf = &(p->storage->getPatch().scene[p->scene - 1].lfo[cge]); - return &(lf->delay); } } lfoEnvelopeDeact; for (int sc = 0; sc < n_scenes; ++sc) { - // TODO: Don't forget to add osc phase here once we add it in XT 2.0! - for (int o = 0; o < n_oscs; ++o) - { - scene[sc].osc[o].pitch.dynamicDeactivation = &oscAudioInDeact; - scene[sc].osc[o].octave.dynamicDeactivation = &oscAudioInDeact; - scene[sc].osc[o].keytrack.dynamicDeactivation = &oscAudioInDeact; - scene[sc].osc[o].retrigger.dynamicDeactivation = &oscAudioInDeact; - } - for (int lf = 0; lf < n_lfos; ++lf) { scene[sc].lfo[lf].start_phase.dynamicName = &lfoPhaseName; @@ -598,10 +570,8 @@ SurgePatch::SurgePatch(SurgeStorage *storage) scene[sc].lfo[lf].rate.dynamicDeactivation = &lfoRatePhaseDeact; auto *curr = &(scene[sc].lfo[lf].delay), *end = &(scene[sc].lfo[lf].release); - curr->deactivated = false; curr++; // we don't want to apply it to delay - while (curr <= end) { curr->dynamicDeactivation = &lfoEnvelopeDeact; @@ -1489,7 +1459,7 @@ void SurgePatch::load_xml(const void *data, int datasize, bool is_preset) } else { - // Explicitly set scene to A. See #2285 + // Explicity set scene to A. See #2285 t.source_scene = 0; } } diff --git a/src/common/SurgeStorage.cpp b/src/common/SurgeStorage.cpp index 0b1cb303eb4..f608faec2ea 100644 --- a/src/common/SurgeStorage.cpp +++ b/src/common/SurgeStorage.cpp @@ -24,8 +24,22 @@ #include "UserDefaults.h" #include "SurgeSharedBinary.h" #include "DebugHelpers.h" +#include "platform/Paths.h" -#include "sst/plugininfra/paths.h" +#if MAC +#include +#include +//#include +//#include +#include +#include +#elif LINUX +#include +#else +#include +#include +#include +#endif #include #include @@ -188,7 +202,18 @@ SurgeStorage::SurgeStorage(std::string suppliedDataPath) : otherscene_clients(0) memset(&audio_in[0][0], 0, 2 * BLOCK_SIZE_OS * sizeof(float)); - bool hasSuppliedDataPath = !suppliedDataPath.empty(); + bool hasSuppliedDataPath = false; + if (suppliedDataPath.size() != 0) + { + hasSuppliedDataPath = true; + } + +#if MAC || LINUX + const auto homePath{Surge::Paths::homePath()}; +#endif + +#if MAC + char path[1024]; std::string buildOverrideDataPath; if (getOverrideDataHome(buildOverrideDataPath)) { @@ -197,83 +222,178 @@ SurgeStorage::SurgeStorage(std::string suppliedDataPath) : otherscene_clients(0) suppliedDataPath = buildOverrideDataPath; } - std::string sxt = "Surge XT"; - std::string sxtlower = "surge-xt"; - -#if MAC if (!hasSuppliedDataPath) { - auto shareddp = sst::plugininfra::paths::bestLibrarySharedFolderPathFor(sxt); - auto userdp = sst::plugininfra::paths::bestLibrarySharedFolderPathFor(sxt, true); + FSRef foundRef; + OSErr err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &foundRef); + FSRefMakePath(&foundRef, (UInt8 *)path, 1024); + std::string localpath = path; + localpath += "/Surge XT/"; - if (fs::is_directory(userdp)) - datapath = userdp; - else - datapath = shareddp; + err = FSFindFolder(kLocalDomain, kApplicationSupportFolderType, false, &foundRef); + FSRefMakePath(&foundRef, (UInt8 *)path, 1024); + std::string rootpath = path; + rootpath += "/Surge XT/"; + + datapath = rootpath; + if (fs::is_directory(string_to_path(localpath))) + datapath = localpath; } else { - datapath = fs::path{suppliedDataPath}; + datapath = suppliedDataPath; } - userDataPath = sst::plugininfra::paths::bestDocumentsFolderPathFor("Surge XT"); + userDataPath = homePath / "Documents/Surge XT"; #elif LINUX if (!hasSuppliedDataPath) { - auto userlower = sst::plugininfra::paths::bestLibrarySharedFolderPathFor(sxtlower, true); - auto userreg = sst::plugininfra::paths::bestLibrarySharedFolderPathFor(sxt, true); - auto globallower = sst::plugininfra::paths::bestLibrarySharedFolderPathFor(sxtlower, false); - auto globalreg = sst::plugininfra::paths::bestLibrarySharedFolderPathFor(sxt, true); + if (const char *xdgDataPath = getenv("XDG_DATA_HOME")) + { + datapath = fs::path{xdgDataPath} / "surge-xt"; + } + else if (auto localDataPath{homePath / ".local/share/surge-xt"}; + fs::is_directory(localDataPath)) + { + datapath = std::move(localDataPath); + } + else + { + datapath = homePath / ".local/share/Surge XT"; + } + + /* + ** If local directory doesn't exists - we probably came here through an installer - + ** check for /usr/share/surge and use /usr/share/Surge as our last guess + */ + if (!fs::is_directory(datapath)) + { + if (fs::is_directory(string_to_path(std::string(Surge::Build::CMAKE_INSTALL_PREFIX)) / + "share" / "surge-xt")) + { + datapath = + string_to_path(Surge::Build::CMAKE_INSTALL_PREFIX) / "share" / "surge-xt"; + } + else if (fs::is_directory(string_to_path(Surge::Build::CMAKE_INSTALL_PREFIX) / "share" / + "Surge XT")) + { + datapath = + string_to_path(Surge::Build::CMAKE_INSTALL_PREFIX) / "share" / "Surge XT"; + } + else + { + std::string systemDataPath = "/usr/share/surge-xt/"; + if (fs::is_directory(string_to_path(systemDataPath))) + datapath = string_to_path(systemDataPath); + else + datapath = string_to_path("/usr/share/Surge XT/"); + } + } - bool founddir{false}; - for (const auto &p : {userreg, userlower, globalreg, globallower}) + std::string buildOverrideDataPath; + if (getOverrideDataHome(buildOverrideDataPath)) { - if (fs::is_directory(p) && !founddir) + datapathOverriden = true; + datapath = buildOverrideDataPath; + static bool warnOver = false; + if (!warnOver) { - founddir = true; - datapath = p; + std::cout << "WARNING: Surge overriding data path to " << datapath << std::endl; + std::cout << " Only use this in build pipelines please!" << std::endl; + warnOver = true; } } - if (!founddir) - datapath = globallower; } else { datapath = suppliedDataPath; } - userDataPath = sst::plugininfra::paths::bestDocumentsFolderPathFor(sxt); + /* + ** See the discussion in github issue #930. Basically + ** if ~/Documents/Surge XT exists use that + ** else if ~/.Surge XT exists use that + ** else if ~/.Documents exists, use ~/Documents/Surge XT + ** else use ~/.Surge XT + ** Compensating for whether your distro makes you a ~/Documents or not + */ + + if (auto xdgdd = getenv("XDG_DOCUMENTS_DIR")) + { + auto xdgpath = fs::path{xdgdd} / "Surge XT"; + userDataPath = std::move(xdgpath); + } + else if (auto documentsSurge = homePath / "Documents/Surge XT"; + fs::is_directory(documentsSurge)) + { + userDataPath = std::move(documentsSurge); + } + else if (auto dotSurge = homePath / ".Surge XT"; fs::is_directory(dotSurge)) + { + userDataPath = std::move(dotSurge); + } + else if (auto documents = homePath / "Documents"; fs::is_directory(documents)) + { + userDataPath = std::move(documentsSurge); + } + else + { + userDataPath = dotSurge; + } + // std::cout << "Data path is " << datapath << std::endl; + // std::cout << "User data path is " << userDataPath << std::endl; #elif WINDOWS - const auto installPath = sst::plugininfra::paths::sharedLibraryBinaryPath().parent_path(); + const auto installPath{Surge::Paths::installPath()}; - if (!hasSuppliedDataPath) + // First check the portable mode sitting beside me + if (auto path{installPath / L"SurgeXTData"}; fs::is_directory(path)) { - // First check the portable mode sitting beside me - if (auto path{installPath / L"SurgeXTData"}; fs::is_directory(path)) - { - datapath = std::move(path); - } + datapath = std::move(path); + } - if (datapath.empty()) + if (datapath.empty()) + { + PWSTR commonAppData; + if (!SHGetKnownFolderPath(FOLDERID_ProgramData, 0, nullptr, &commonAppData)) { - datapath = sst::plugininfra::paths::bestLibrarySharedFolderPathFor(sxt); + fs::path path(commonAppData); + path /= L"Surge XT"; + if (fs::is_directory(path)) + { + datapath = path_to_string(path); + } } + } - if (datapath.empty() || !fs::is_directory(datapath)) + if (datapath.empty()) + { + PWSTR localAppData; + if (!SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &localAppData)) { - datapath = sst::plugininfra::paths::bestLibrarySharedFolderPathFor(sxt, true); + fs::path path(localAppData); + path /= L"Surge XT"; + datapath = path_to_string(path); } } + std::string orPath; + if (getOverrideDataHome(orPath)) + { + datapathOverriden = true; + datapath = orPath; + } + // Portable - first check for installPath\\SurgeXTUserData if (auto path{installPath / L"SurgeXTUserData"}; fs::is_directory(path)) { userDataPath = std::move(path); } - else + else if (PWSTR documentsFolder; + !SHGetKnownFolderPath(FOLDERID_Documents, 0, nullptr, &documentsFolder)) { - userDataPath = sst::plugininfra::paths::bestDocumentsFolderPathFor(sxt); + userDataPath = fs::path{documentsFolder} / L"Surge XT"; + // FIXME: Don't leak documentsFolder! } #endif @@ -283,7 +403,7 @@ SurgeStorage::SurgeStorage(std::string suppliedDataPath) : otherscene_clients(0) Surge::Storage::getUserDefaultValue(this, Surge::Storage::UserDataPath, "UNSPEC"); if (userSpecifiedDataPath != "UNSPEC") { - userDataPath = fs::path{userSpecifiedDataPath}; + userDataPath = userSpecifiedDataPath; } // append separator if not present @@ -296,6 +416,17 @@ SurgeStorage::SurgeStorage(std::string suppliedDataPath) : otherscene_clients(0) userSkinsPath = userDataPath / "Skins"; createUserDirectory(); + /* + const auto snapshotmenupath{string_to_path(datapath + "configuration.xml")}; + + if (!snapshotloader.LoadFile(snapshotmenupath)) // load snapshots (& config-stuff) + { + reportError("Cannot find 'configuration.xml' in path '" + + datapath + "'. Please reinstall surge.", + "Surge is not properly installed."); + } + */ + // TIXML requires a newline at end. auto cxmlData = std::string(SurgeSharedBinary::configuration_xml, SurgeSharedBinary::configuration_xmlSize) + @@ -687,7 +818,7 @@ void SurgeStorage::refreshPatchOrWTListAddDir(bool userDir, string subdir, /* ** std::filesystem has a recursive_directory_iterator, but between the - ** hand rolled ipmmlementation on mac, experimental on windows, and + ** hand rolled ipmmlementation on mac, expermiental on windows, and ** ostensibly standard on linux it isn't consistent enough to warrant ** using yet, so build my own recursive directory traversal with a simple ** stack @@ -2291,7 +2422,7 @@ bool isValidUTF8(const std::string &testThis) // then it's always of form '110xxxxx10xxxxxx'. Similarly for three and four byte UTF8 // characters it starts with '1110xxxx' and '11110xxx' followed by '10xxxxxx' one less times as // there are bytes. This tool will locate mistakes in the encoding and tell you where they - // occurred. + // occured. // https://helloacm.com/how-to-validate-utf-8-encoding-the-simple-utf-8-validation-algorithm/ diff --git a/src/common/SurgeStorage.h b/src/common/SurgeStorage.h index 890ca12ab71..67f3de82ed4 100644 --- a/src/common/SurgeStorage.h +++ b/src/common/SurgeStorage.h @@ -72,7 +72,7 @@ const int FIRoffsetI16 = FIRipolI16_N >> 1; // 2 -> 3 filter subtypes added: Comb defaults to 1, Legacy Ladder defaults to 3 // 3 -> 4 Comb+ and Comb- are now combined into one filter type // (type, subtype: +, 0 -> 0 | +, 1 -> 1 | -, 0 -> 2 | -, 1 -> 3) -// 4 -> 5 Stereo filter configuration has separate pan controls now +// 4 -> 5 Stereo filter configuration has seperate pan controls now // 5 -> 6 (1.2.0 release) filter resonance response changed (same parameters, different sound) // 6 -> 7 custom controller state now stored in DAW recall // 7 -> 8 larger resonance range (old filters are set to subtype 1) @@ -167,7 +167,6 @@ enum deform_type type_1, type_2, type_3, - type_4, n_deform_types, }; @@ -907,7 +906,7 @@ class SurgePatch int currentSynthStreamingRevision; /* - * This parameter exists for the very special reason of maintaining compatibility with + * This parameter exists for the very special reason of maintaing compatibility with * comb filter tuning for streaming versions which are older than Surge v1.8. * Prior to that, the comb filter had a calculation error in the time and was out of tune, * but that lead to a unique sound in existing patches. So we introduce this parameter @@ -992,7 +991,7 @@ class alignas(16) SurgeStorage struct ErrorListener { // This can be called from any thread. Beware. But it is called only - // when an error occurs so if you want to be sloppy and just lock that's OK + // when an error occurs so if you want to be sloppy and just lock thats OK virtual void onSurgeError(const std::string &msg, const std::string &title) = 0; }; std::unordered_set errorListeners; diff --git a/src/common/SurgeSynthesizer.cpp b/src/common/SurgeSynthesizer.cpp index f9b6cc48ff5..08bb2936537 100644 --- a/src/common/SurgeSynthesizer.cpp +++ b/src/common/SurgeSynthesizer.cpp @@ -34,11 +34,8 @@ using namespace std; using CMSKey = ControllerModulationSourceVector<1>; // sigh see #4286 for failed first try SurgeSynthesizer::SurgeSynthesizer(PluginLayer *parent, const std::string &suppliedDataPath) - : storage(suppliedDataPath), hpA{&storage, &storage, &storage, &storage}, hpB{&storage, - &storage, - &storage, - &storage}, - _parent(parent), halfbandA(6, true), halfbandB(6, true), halfbandIN(6, true) + : storage(suppliedDataPath), hpA(&storage), hpB(&storage), _parent(parent), halfbandA(6, true), + halfbandB(6, true), halfbandIN(6, true) { switch_toggled_queued = false; audio_processing_active = false; @@ -961,7 +958,7 @@ void SurgeSynthesizer::releaseNote(char channel, char key, char velocity) releaseNotePostHoldCheck(sc, channel, key, velocity); else holdbuffer[sc].push_back( - HoldBufferItem{channel, key, channel, key}); // hold pedal is down, add to buffer + HoldBufferItem{channel, key, channel, key}); // hold pedal is down, add to bufffer } } @@ -1029,7 +1026,7 @@ void SurgeSynthesizer::releaseNotePostHoldCheck(int scene, char channel, char ke if ((v->state.key == key) && (v->state.channel == channel)) { - int activateVoiceKey = 60, activateVoiceChannel = 0; // these will be overridden + int activateVoiceKey = 60, activateVoiceChannel = 0; // these will be overriden auto priorityMode = storage.getPatch().scene[v->state.scene_id].monoVoicePriorityMode; @@ -2044,11 +2041,8 @@ void SurgeSynthesizer::allNotesOff() halfbandB.reset(); halfbandIN.reset(); - for (int i = 0; i < n_hpBQ; i++) - { - hpA[i].suspend(); - hpB[i].suspend(); - } + hpA.suspend(); + hpB.suspend(); for (int i = 0; i < n_fx_slots; i++) { @@ -2240,7 +2234,7 @@ bool SurgeSynthesizer::setParameter01(long index, float value, bool external, bo if (storage.getPatch().param_ptr[index]->val.i != oldval.i) { /* - ** Wish there was a better way to figure out my osc but this works + ** Wish there was a better way to figure out my osc but thsi works */ for (auto oi = 0; s >= 0 && s <= 1 && oi < n_oscs; oi++) { @@ -3926,13 +3920,8 @@ void SurgeSynthesizer::process() auto freq = storage.getPatch().scenedata[0][storage.getPatch().scene[0].lowcut.param_id_in_scene].f; - auto slope = storage.getPatch().scene[0].lowcut.deform_type; - - for (int i = 0; i <= slope; i++) - { - hpA[i].coeff_HP(hpA[i].calc_omega(freq / 12.0), 0.4); // var 0.707 - hpA[i].process_block(sceneout[0][0], sceneout[0][1]); // TODO: quadify - } + hpA.coeff_HP(hpA.calc_omega(freq / 12.0), 0.4); // var 0.707 + hpA.process_block(sceneout[0][0], sceneout[0][1]); // TODO: quadify } if (storage.getPatch().scene[1].lowcut.deactivated == false) @@ -3940,13 +3929,8 @@ void SurgeSynthesizer::process() auto freq = storage.getPatch().scenedata[1][storage.getPatch().scene[1].lowcut.param_id_in_scene].f; - auto slope = storage.getPatch().scene[1].lowcut.deform_type; - - for (int i = 0; i <= slope; i++) - { - hpB[i].coeff_HP(hpB[i].calc_omega(freq / 12.0), 0.4); // var 0.707 - hpB[i].process_block(sceneout[1][0], sceneout[1][1]); // TODO: quadify - } + hpB.coeff_HP(hpB.calc_omega(freq / 12.0), 0.4); + hpB.process_block(sceneout[1][0], sceneout[1][1]); } for (int cls = 0; cls < n_scenes; ++cls) diff --git a/src/common/SurgeSynthesizer.h b/src/common/SurgeSynthesizer.h index 44508b272db..9bf299253a0 100644 --- a/src/common/SurgeSynthesizer.h +++ b/src/common/SurgeSynthesizer.h @@ -280,8 +280,8 @@ class alignas(16) SurgeSynthesizer /* * setModulation etc take a modsource scene. This is only needed for global modulations - * since for in-scene modulations the parameter implicit in ptag has a scene. But for - * LFOs modulating FX, we need to know which scene they originate from. See #2285 + * since for in-scene modulations the paramter implicit in ptag has a scene. But for + * LFOs modulating FX, we need to knwo which scene they originate from. See #2285 */ bool setModulation(long ptag, modsources modsource, int modsourceScene, int index, float value); float getModulation(long ptag, modsources modsource, int modsourceScene, int index) const; @@ -381,10 +381,7 @@ class alignas(16) SurgeSynthesizer bool switch_toggled_queued, release_if_latched[n_scenes], release_anyway[n_scenes]; void setParameterSmoothed(long index, float value); - - static constexpr int n_hpBQ = 4; - - std::array hpA, hpB; // TODO: FIX SCENE ASSUMPTION (use std::array) + BiquadFilter hpA, hpB; // TODO: FIX SCENE ASSUMPTION (use std::array) bool fx_reload[n_fx_slots]; // if true, reload new effect parameters from fxsync FxStorage fxsync[n_fx_slots]; // used for synchronisation of parameter init diff --git a/src/common/SurgeSynthesizerIO.cpp b/src/common/SurgeSynthesizerIO.cpp index a64acbf9a26..f28ef78d912 100644 --- a/src/common/SurgeSynthesizerIO.cpp +++ b/src/common/SurgeSynthesizerIO.cpp @@ -534,7 +534,7 @@ void SurgeSynthesizer::savePatch(bool factoryInPlace) catch (...) { storage.reportError( - "Exception occurred while creating category folder! Most likely, invalid characters " + "Exception occured while creating category folder! Most likely, invalid characters " "were used to name the category. Please remove suspicious characters and try again!", "Error"); return; diff --git a/src/common/dsp/Effect.h b/src/common/dsp/Effect.h index d002d150118..aec91613128 100644 --- a/src/common/dsp/Effect.h +++ b/src/common/dsp/Effect.h @@ -64,7 +64,7 @@ class alignas(16) Effect float vu[KNumVuSlots]; // stereo pairs, just use every other when mono // Most of the fx read the sample rate at sample time but airwindows - // keeps a cache so give loaded fx a notice when the sample rate changes + // keeps a cache so give loaded fx a notice when the sample rate cahnges virtual void sampleRateReset() {} virtual void handleStreamingMismatches(int streamingRevision, int currentSynthStreamingRevision) @@ -85,7 +85,7 @@ class alignas(16) Effect pdata *pd; int ringout; float *f[n_fx_params]; - int *pdata_ival[n_fx_params]; // f is not a great choice for a member name, but 'i' would be + int *pdata_ival[n_fx_params]; // f is not a great choice for a member name, but 'i' woudl be // worse! bool hasInvalidated{false}; }; diff --git a/src/common/dsp/QuadFilterChain.h b/src/common/dsp/QuadFilterChain.h index 60c05bcb83e..269410d1964 100644 --- a/src/common/dsp/QuadFilterChain.h +++ b/src/common/dsp/QuadFilterChain.h @@ -78,7 +78,7 @@ * of registers (storage) and coefficients (inputs) to each filter based on the filter type at * the start of every block. Moreover, it provides the derivatives-with-respect-to-sample of * those items, such that as the filter goes across the block it can smoothly interpolate the - * coefficients. These are set up either by direct change (with FromDirect) or individually + * coeffiecients. These are set up either by direct change (with FromDirect) or individually * based on filters. And of course, this is where a lot of the math goes. The SSE filters need * to set up the various polynomial and non-linear coefficients here. But once they have the * individual operator, they basically do a "Coefficient += dCoeff" for each block and then evaluate @@ -92,8 +92,8 @@ * * Finally, the filter types, subtypes and names thereof are enumerated in SurgeStorage.h. * - * There are a few more Surge filter functions - the Allpass BiquadFilter and VectorizedSVFFilter - * are used by various FX in a different context and they don't follow this architecture. That code + * There are a few more Surge fitler functions - the Allpass BiquadFilter and VectorizedSVFFilter + * are used by various FX in a different context and they don't follow this architecutre. That code * is fairly clear, though. */ @@ -102,7 +102,7 @@ struct QuadFilterChainState { - QuadFilterUnitState FU[4]; // 2 filters left and right + QuadFilterUnitState FU[4]; // 2 filters left and righ QuadFilterWaveshaperState WSS[2]; // 1 shaper left and right __m128 Gain, FB, Mix1, Mix2, Drive; diff --git a/src/common/dsp/QuadFilterUnit.h b/src/common/dsp/QuadFilterUnit.h index c25eb290c56..0eec070acff 100644 --- a/src/common/dsp/QuadFilterUnit.h +++ b/src/common/dsp/QuadFilterUnit.h @@ -22,7 +22,7 @@ FilterUnitQFPtr GetQFPtrFilterUnit(int type, int subtype); /* * Subtypes are integers below 16 - maybe one day go as high as 32. So we have space in the * int for more informatino and we mask on higher bits to allow us to - * programmatically change features we don't expose to users, in things like + * programatically change features we don't expose to users, in things like * FX. So far this is only used to extend the COMB time in the combulator. * * These should obvioulsy be distinct per type but can overlap in values otherwise diff --git a/src/common/dsp/SurgeVoice.cpp b/src/common/dsp/SurgeVoice.cpp index 323f2241375..03e62800cb1 100644 --- a/src/common/dsp/SurgeVoice.cpp +++ b/src/common/dsp/SurgeVoice.cpp @@ -1148,7 +1148,7 @@ void SurgeVoice::SetQFB(QuadFilterChainState *Q, int e) // Q == 0 means init(ial if (!Q) { - // We need to initialize the waveshaper registers + // We need to initalize the waveshaper registers for (int c = 0; c < 2; ++c) initializeWaveshaperRegister(scene->wsunit.type.val.i, FBP.WS[c].R); } diff --git a/src/common/dsp/SurgeVoice.h b/src/common/dsp/SurgeVoice.h index 071375de3ac..6818e02d09d 100644 --- a/src/common/dsp/SurgeVoice.h +++ b/src/common/dsp/SurgeVoice.h @@ -56,7 +56,7 @@ class alignas(16) SurgeVoice int age, age_release; /* - ** Given a note0 and an oscillator this returns the appropriate note. + ** Given a note0 and an oscilator this returns the appropriate note. ** This is a pretty easy calculation in non-absolute mode. Just add. ** But in absolute mode you need to find the virtual note which would ** map to that frequency shift. diff --git a/src/common/dsp/effects/NimbusEffect.h b/src/common/dsp/effects/NimbusEffect.h index 4a9323dee9a..1be46fc9b10 100644 --- a/src/common/dsp/effects/NimbusEffect.h +++ b/src/common/dsp/effects/NimbusEffect.h @@ -82,7 +82,7 @@ class NimbusEffect : public Effect static constexpr int raw_out_sz = BLOCK_SIZE_OS << 3; // power of 2 pls float resampled_output[raw_out_sz][2]; // at sr size_t resampReadPtr = 0, resampWritePtr = 1; // see comment in init - float stub_input[2]; // This is the extra sample we have around + float stub_input[2]; // This is the extra sample we ahve around bool hasStubInput = false; int consumed = 0, created = 0; }; diff --git a/src/common/dsp/effects/ResonatorEffect.cpp b/src/common/dsp/effects/ResonatorEffect.cpp index 986c489a2ab..0fc977d744c 100644 --- a/src/common/dsp/effects/ResonatorEffect.cpp +++ b/src/common/dsp/effects/ResonatorEffect.cpp @@ -190,7 +190,7 @@ void ResonatorEffect::process(float *dataL, float *dataR) for (int s = 0; s < BLOCK_SIZE_OS; ++s) { // preprocess audio in through asymmetric waveshaper - // this mimics Polymoog's power supply which only operated on positive rails + // this mimicks Polymoog's power supply which only operated on positive rails dataOS[0][s] = lookup_waveshape(wst_asym, dataOS[0][s]); dataOS[1][s] = lookup_waveshape(wst_asym, dataOS[1][s]); diff --git a/src/common/dsp/effects/airwindows/AirWindowsEffect.cpp b/src/common/dsp/effects/airwindows/AirWindowsEffect.cpp index a25a1ccfc1d..3c369300cdf 100644 --- a/src/common/dsp/effects/airwindows/AirWindowsEffect.cpp +++ b/src/common/dsp/effects/airwindows/AirWindowsEffect.cpp @@ -80,7 +80,7 @@ void AirWindowsEffect::init_ctrltypes() ** can set values, then when we process later, resetCtrlTypes ** will take those prior values and assign them as new (and that's ** what is called if the value is changed). Also since the load - ** will often load to a separate instance and copy the params over + ** will often load to a sparate instance and copy the params over ** we set the user_data to nullptr here to indicate that ** after this inti we need to do something even if the value ** of our FX hasn't changed. diff --git a/src/common/dsp/effects/chowdsp/TapeEffect.cpp b/src/common/dsp/effects/chowdsp/TapeEffect.cpp index 1031810ab10..abb77feb1ed 100644 --- a/src/common/dsp/effects/chowdsp/TapeEffect.cpp +++ b/src/common/dsp/effects/chowdsp/TapeEffect.cpp @@ -139,7 +139,7 @@ int TapeEffect::group_label_ypos(int id) void TapeEffect::init_ctrltypes() { /* - * The actually deactivation status is on gain, so reflect that down + * The actualy deactivation status is on gain, so reflet that down * to freq and bw using the dynamic deactivation mechanism */ static struct TapeEffectDeact : public ParameterDynamicDeactivationFunction diff --git a/src/common/dsp/effects/chowdsp/bbd_utils/BBDNonlin.h b/src/common/dsp/effects/chowdsp/bbd_utils/BBDNonlin.h index 955acbb76b1..f396b03dea1 100644 --- a/src/common/dsp/effects/chowdsp/bbd_utils/BBDNonlin.h +++ b/src/common/dsp/effects/chowdsp/bbd_utils/BBDNonlin.h @@ -48,7 +48,7 @@ class FastDiode : public chowdsp::WDF_SSE::WDFNode /** Accepts an incident wave into a WDF diode. */ inline void incident(__m128 x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF diode. */ + /** Propogates a reflected wave from a WDF diode. */ inline __m128 reflected() noexcept override { // See eqn (10) from reference paper diff --git a/src/common/dsp/effects/chowdsp/shared/FIRFIlter.h b/src/common/dsp/effects/chowdsp/shared/FIRFIlter.h index fd672b51f11..7a537625a53 100644 --- a/src/common/dsp/effects/chowdsp/shared/FIRFIlter.h +++ b/src/common/dsp/effects/chowdsp/shared/FIRFIlter.h @@ -6,7 +6,7 @@ namespace chowdsp { /* -** Simple class for FIR filtering. +** Simple class fro FIR filtering. ** For the original implementation, ** see: https://github.com/jatinchowdhury18/FIRBenchmarks/blob/master/src/InnerProdFIR.h */ diff --git a/src/common/dsp/effects/chowdsp/shared/chowdsp_IIR.h b/src/common/dsp/effects/chowdsp/shared/chowdsp_IIR.h index aaafecba7c3..428cd04ca19 100644 --- a/src/common/dsp/effects/chowdsp/shared/chowdsp_IIR.h +++ b/src/common/dsp/effects/chowdsp/shared/chowdsp_IIR.h @@ -6,7 +6,7 @@ namespace chowdsp { -/** IIR filter of arbitrary order. +/** IIR filter of arbirtary order. * Uses Transposed Direct Form II: * https://ccrma.stanford.edu/~jos/fp/Transposed_Direct_Forms.html */ diff --git a/src/common/dsp/effects/chowdsp/shared/wdf.h b/src/common/dsp/effects/chowdsp/shared/wdf.h index 12a52368771..6612981e9c5 100644 --- a/src/common/dsp/effects/chowdsp/shared/wdf.h +++ b/src/common/dsp/effects/chowdsp/shared/wdf.h @@ -66,7 +66,7 @@ class WDF */ virtual void calcImpedance() = 0; - /** Sub-classes override this function to propagate + /** Sub-classes override this function to propogate * an impedance change to the upstream elements in * the WDF tree. */ @@ -75,7 +75,7 @@ class WDF /** Sub-classes override this function to accept an incident wave. */ virtual void incident(double x) noexcept = 0; - /** Sub-classes override this function to propagate a reflected wave. */ + /** Sub-classes override this function to propogate a reflected wave. */ virtual double reflected() noexcept = 0; /** Probe the voltage across this circuit element. */ @@ -116,7 +116,7 @@ class WDFNode : public WDF /** When this function is called from a downstream * element in the WDF tree, the impedance is recomputed - * and then propagated upstream to the next element in the + * and then propogated upstream to the next element in the * WDF tree. */ inline void propagateImpedance() override @@ -161,7 +161,7 @@ class Resistor : public WDFNode /** Accepts an incident wave into a WDF resistor. */ inline void incident(double x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF resistor. */ + /** Propogates a reflected wave from a WDF resistor. */ inline double reflected() noexcept override { b = 0.0; @@ -218,7 +218,7 @@ class Capacitor : public WDFNode z = a; } - /** Propagates a reflected wave from a WDF capacitor. */ + /** Propogates a reflected wave from a WDF capacitor. */ inline double reflected() noexcept override { b = b_coef * b + a_coef * z; @@ -280,7 +280,7 @@ class Inductor : public WDFNode z = a; } - /** Propagates a reflected wave from a WDF inductor. */ + /** Propogates a reflected wave from a WDF inductor. */ inline double reflected() noexcept override { b = b_coef * b - a_coef * z; @@ -313,7 +313,7 @@ class Switch : public WDFNode /** Accepts an incident wave into a WDF switch. */ inline void incident(double x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF switch. */ + /** Propogates a reflected wave from a WDF switch. */ inline double reflected() noexcept override { b = closed ? -a : a; @@ -340,7 +340,7 @@ class Open : public WDFNode /** Accepts an incident wave into a WDF open. */ inline void incident(double x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF open. */ + /** Propogates a reflected wave from a WDF open. */ inline double reflected() noexcept override { b = a; @@ -364,7 +364,7 @@ class Short : public WDFNode /** Accepts an incident wave into a WDF short. */ inline void incident(double x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF short. */ + /** Propogates a reflected wave from a WDF short. */ inline double reflected() noexcept override { b = -a; @@ -402,7 +402,7 @@ class PolarityInverter : public WDFNode port1->incident(-x); } - /** Propagates a reflected wave from a WDF inverter. */ + /** Propogates a reflected wave from a WDF inverter. */ inline double reflected() noexcept override { b = -port1->reflected(); @@ -443,7 +443,7 @@ template class PolarityInverterT : public WDFNode port1->incident(-x); } - /** Propagates a reflected wave from a WDF inverter. */ + /** Propogates a reflected wave from a WDF inverter. */ inline double reflected() noexcept override { b = -port1->reflected(); @@ -557,7 +557,7 @@ class WDFParallel : public WDFAdaptor a = x; } - /** Propagates a reflected wave from a WDF parallel adaptor. */ + /** Propogates a reflected wave from a WDF parallel adaptor. */ inline double reflected() noexcept override { b = port1Reflect * port1->reflected() + port2Reflect * port2->reflected(); @@ -609,7 +609,7 @@ template class WDFParallelT : public WD a = x; } - /** Propagates a reflected wave from a WDF parallel adaptor. */ + /** Propogates a reflected wave from a WDF parallel adaptor. */ inline double reflected() noexcept override { b = port1Reflect * port1->reflected() + port2Reflect * port2->reflected(); @@ -655,7 +655,7 @@ class WDFSeries : public WDFAdaptor a = x; } - /** Propagates a reflected wave from a WDF series adaptor. */ + /** Propogates a reflected wave from a WDF series adaptor. */ inline double reflected() noexcept override { b = -(port1->reflected() + port2->reflected()); @@ -706,7 +706,7 @@ template class WDFSeriesT : public WDFN a = x; } - /** Propagates a reflected wave from a WDF series adaptor. */ + /** Propogates a reflected wave from a WDF series adaptor. */ inline double reflected() noexcept override { b = -(port1->reflected() + port2->reflected()); @@ -744,7 +744,7 @@ class ResistiveVoltageSource : public WDFNode propagateImpedance(); } - /** Computes the impedance for a WDF resistive voltage source + /** Computes the impedance for a WDF resistive voltage souce * Z_Vr = Z_R */ inline void calcImpedance() override @@ -759,7 +759,7 @@ class ResistiveVoltageSource : public WDFNode /** Accepts an incident wave into a WDF resistive voltage source. */ inline void incident(double x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF resistive voltage source. */ + /** Propogates a reflected wave from a WDF resistive voltage source. */ inline double reflected() noexcept override { b = Vs; @@ -786,7 +786,7 @@ class IdealVoltageSource : public WDFNode /** Accepts an incident wave into a WDF ideal voltage source. */ inline void incident(double x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF ideal voltage source. */ + /** Propogates a reflected wave from a WDF ideal voltage source. */ inline double reflected() noexcept override { b = -a + 2.0 * Vs; @@ -820,7 +820,7 @@ class ResistiveCurrentSource : public WDFNode propagateImpedance(); } - /** Computes the impedance for a WDF resistive current source + /** Computes the impedance for a WDF resistive current souce * Z_Ir = Z_R */ inline void calcImpedance() override @@ -835,7 +835,7 @@ class ResistiveCurrentSource : public WDFNode /** Accepts an incident wave into a WDF resistive current source. */ inline void incident(double x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF resistive current source. */ + /** Propogates a reflected wave from a WDF resistive current source. */ inline double reflected() noexcept override { b = 2 * R * Is; @@ -862,7 +862,7 @@ class IdealCurrentSource : public WDFNode /** Accepts an incident wave into a WDF ideal current source. */ inline void incident(double x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF ideal current source. */ + /** Propogates a reflected wave from a WDF ideal current source. */ inline double reflected() noexcept override { b = 2 * next->R * Is + a; @@ -896,7 +896,7 @@ class DiodePair : public WDFNode /** Accepts an incident wave into a WDF diode pair. */ inline void incident(double x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF diode pair. */ + /** Propogates a reflected wave from a WDF diode pair. */ inline double reflected() noexcept override { // See eqn (18) from reference paper @@ -932,7 +932,7 @@ class Diode : public WDFNode /** Accepts an incident wave into a WDF diode. */ inline void incident(double x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF diode. */ + /** Propogates a reflected wave from a WDF diode. */ inline double reflected() noexcept override { // See eqn (10) from reference paper diff --git a/src/common/dsp/effects/chowdsp/shared/wdf_sse.h b/src/common/dsp/effects/chowdsp/shared/wdf_sse.h index b107b67ae8a..641723be619 100644 --- a/src/common/dsp/effects/chowdsp/shared/wdf_sse.h +++ b/src/common/dsp/effects/chowdsp/shared/wdf_sse.h @@ -45,7 +45,7 @@ class WDF */ virtual void calcImpedance() = 0; - /** Sub-classes override this function to propagate + /** Sub-classes override this function to propogate * an impedance change to the upstream elements in * the WDF tree. */ @@ -54,7 +54,7 @@ class WDF /** Sub-classes override this function to accept an incident wave. */ virtual void incident(__m128 x) noexcept = 0; - /** Sub-classes override this function to propagate a reflected wave. */ + /** Sub-classes override this function to propogate a reflected wave. */ virtual __m128 reflected() noexcept = 0; /** Probe the voltage across this circuit element. */ @@ -95,7 +95,7 @@ class WDFNode : public WDF /** When this function is called from a downstream * element in the WDF tree, the impedance is recomputed - * and then propagated upstream to the next element in the + * and then propogated upstream to the next element in the * WDF tree. */ inline void propagateImpedance() override @@ -141,7 +141,7 @@ class Resistor : public WDFNode /** Accepts an incident wave into a WDF resistor. */ inline void incident(__m128 x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF resistor. */ + /** Propogates a reflected wave from a WDF resistor. */ inline __m128 reflected() noexcept override { b = vLoad1(0.0f); @@ -199,7 +199,7 @@ class Capacitor : public WDFNode z = a; } - /** Propagates a reflected wave from a WDF capacitor. */ + /** Propogates a reflected wave from a WDF capacitor. */ inline __m128 reflected() noexcept override { b = vAdd(vMul(b_coef, b), vMul(a_coef, z)); @@ -247,7 +247,7 @@ template class PolarityInverterT : public WDFNode port1->incident(vNeg(x)); } - /** Propagates a reflected wave from a WDF inverter. */ + /** Propogates a reflected wave from a WDF inverter. */ inline __m128 reflected() noexcept override { b = vNeg(port1->reflected()); @@ -297,7 +297,7 @@ template class WDFParallelT : public WD a = x; } - /** Propagates a reflected wave from a WDF parallel adaptor. */ + /** Propogates a reflected wave from a WDF parallel adaptor. */ inline __m128 reflected() noexcept override { b = vAdd(vMul(port1Reflect, port1->reflected()), vMul(port2Reflect, port2->reflected())); @@ -351,7 +351,7 @@ template class WDFSeriesT : public WDFN a = x; } - /** Propagates a reflected wave from a WDF series adaptor. */ + /** Propogates a reflected wave from a WDF series adaptor. */ inline __m128 reflected() noexcept override { b = vNeg(vAdd(port1->reflected(), port2->reflected())); @@ -391,7 +391,7 @@ class ResistiveVoltageSource : public WDFNode propagateImpedance(); } */ - /** Computes the impedance for a WDF resistive voltage source + /** Computes the impedance for a WDF resistive voltage souce * Z_Vr = Z_R */ inline void calcImpedance() override @@ -406,7 +406,7 @@ class ResistiveVoltageSource : public WDFNode /** Accepts an incident wave into a WDF resistive voltage source. */ inline void incident(__m128 x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF resistive voltage source. */ + /** Propogates a reflected wave from a WDF resistive voltage source. */ inline __m128 reflected() noexcept override { b = Vs; @@ -443,7 +443,7 @@ class ResistiveCurrentSource : public WDFNode propagateImpedance(); } */ - /** Computes the impedance for a WDF resistive current source + /** Computes the impedance for a WDF resistive current souce * Z_Ir = Z_R */ inline void calcImpedance() override @@ -458,7 +458,7 @@ class ResistiveCurrentSource : public WDFNode /** Accepts an incident wave into a WDF resistive current source. */ inline void incident(__m128 x) noexcept override { a = x; } - /** Propagates a reflected wave from a WDF resistive current source. */ + /** Propogates a reflected wave from a WDF resistive current source. */ inline __m128 reflected() noexcept override { b = vMul(vLoad1(2.0f), vMul(R, Is)); diff --git a/src/common/dsp/filters/TriPoleFilter.cpp b/src/common/dsp/filters/TriPoleFilter.cpp index 3ec3da6c833..029e3c93f44 100644 --- a/src/common/dsp/filters/TriPoleFilter.cpp +++ b/src/common/dsp/filters/TriPoleFilter.cpp @@ -18,7 +18,7 @@ ** The filter has three output points. For modes and three output ** points makes for a total of 12 sub-types. ** -** The details of the emulation are derived in a Python notebook here: +** The details of the emulation are derived in a Pyton notebook here: ** https://github.com/surge-synthesizer/surge-python/blob/main/scripts/dsp_simulations/ThreelerAnalysis.ipynb */ diff --git a/src/common/dsp/filters/VintageLadders.cpp b/src/common/dsp/filters/VintageLadders.cpp index 0db885f7bb3..11633395b55 100644 --- a/src/common/dsp/filters/VintageLadders.cpp +++ b/src/common/dsp/filters/VintageLadders.cpp @@ -63,7 +63,7 @@ namespace RK ** where k controls the cutoff frequency, r is feedback (<= 4 for stability), and S(x) is a *saturation function. ** -** Although the code is modified from that location here is the original copyright notice: +** Although the code is modified from that location here is the originaly copyright notice: ** ** Copyright (c) 2015, Miller Puckette. All rights reserved. ** @@ -234,7 +234,7 @@ __m128 process(QuadFilterUnitState *__restrict f, __m128 input) ** OK this is a bit of a hack but... these are the Lanczos factors ** sinc( x ) sinc (x / 2), only backwards. Really we should do a proper little ** FIR around the whole thing, but this at least gives us a reconstruction with - ** some aliasing suppression. + ** some aliasing supression. ** ** Not entirely valid but... ** diff --git a/src/common/dsp/modulators/ADSRModulationSource.h b/src/common/dsp/modulators/ADSRModulationSource.h index d06cefcd586..b1bf557b9b8 100644 --- a/src/common/dsp/modulators/ADSRModulationSource.h +++ b/src/common/dsp/modulators/ADSRModulationSource.h @@ -280,18 +280,22 @@ class ADSRModulationSource : public ModulationSource /* ** That + rate * rate in both means at low sustain ( < 1e-3 or so) you end up - ** with lo and hi both pushing us up off sustain. Unfortunately we need to - ** handle that case specially by pushing lo down. These limits are pretty - ** empirical. Git blame to see the various issues around here which show the - ** test cases. + *with + ** lo and hi both pushing us up off sustain. Unfortunatley we ned to handle that + *case + ** specially by pushing lo down. These limits are pretty empirical. Git blame to + *see + ** the various issues around here which show the test cases. */ if ((lc[s].f < 1e-3 && phase < 1e-4) || (lc[s].f == 0 && lc[d].f < -7)) l_lo = 0; /* ** Similarly if the rate is very high - larger than one - we can push l_lo well - ** above the sustain, which can set back a feedback cycle where we bounce onto - ** sustain and off again. To understand this, remove this bound and play with - ** test-data/patches/ADSR-Self-Oscillate.fxp + *above the + ** sustain, which can set back a feedback cycle where we bounce onto sustain and + *off again. + ** To understand this, remove this bound and play with + *test-data/patches/ADSR-Self-Oscillate.fxp */ if (rate > 1.0 && l_lo > lc[s].f) l_lo = lc[s].f; diff --git a/src/common/dsp/modulators/FormulaModulationHelper.cpp b/src/common/dsp/modulators/FormulaModulationHelper.cpp index 19a659f1130..1e7d08f6475 100644 --- a/src/common/dsp/modulators/FormulaModulationHelper.cpp +++ b/src/common/dsp/modulators/FormulaModulationHelper.cpp @@ -156,7 +156,7 @@ end } else { - s.adderror("Unable to determine 'process' or 'init' function : " + emsg); + s.adderror("Unable to deteremine 'process' or 'init' function : " + emsg); lua_pop(s.L, 1); // process lua_pop(s.L, 1); // process stateData.knownBadFunctions.insert(s.funcName); @@ -221,7 +221,7 @@ end { s.isvalid = false; s.adderror("Your 'init' function must return a table. This usually means " - "that you didn't end your init function with 'return modstate' " + "that you didnt' end your init function with 'return modstate' " "before the end statement."); stateData.knownBadFunctions.insert(s.funcName); } diff --git a/src/common/dsp/modulators/FormulaModulationHelper.h b/src/common/dsp/modulators/FormulaModulationHelper.h index 522bdf30edb..cb80e38e0ad 100644 --- a/src/common/dsp/modulators/FormulaModulationHelper.h +++ b/src/common/dsp/modulators/FormulaModulationHelper.h @@ -114,7 +114,7 @@ std::string createDebugViewOfModState(const EvaluatorState &s); /* * Our test harness wants to send bits of lua to the modstate to get results out for - * regtests. Send a function query(modstate) which returns something leaf like + * regtests. Send a function query(modstate) which returns somethign leaf like */ std::variant runOverModStateForTesting(const std::string &query, const EvaluatorState &s); diff --git a/src/common/dsp/modulators/LFOModulationSource.cpp b/src/common/dsp/modulators/LFOModulationSource.cpp index d138cd3f7af..f1bdbb6d3f3 100644 --- a/src/common/dsp/modulators/LFOModulationSource.cpp +++ b/src/common/dsp/modulators/LFOModulationSource.cpp @@ -529,7 +529,7 @@ void LFOModulationSource::process_block() } else phase = - 0; // should never get here but something is already weird with the mod stack + 0; // should never get here but something is already wierd with the mod stack } else { @@ -570,7 +570,7 @@ void LFOModulationSource::process_block() case lt_stepseq: /* ** You might thing we don't need this and technically we don't - ** but I wanted to keep it here to retain compatibility with + ** but I wanted to keep it here to retain compatability with ** versions of trigmask which were streamed in older sessions */ if (ss->trigmask & (UINT64_C(1) << step)) @@ -782,7 +782,7 @@ void LFOModulationSource::process_block() if (frate == 0) { /* - ** Alright so in 0 rate mode we want to scrub through the entire sequence. So + ** Alright so in 0 rate mode we want to scrub through tne entire sequence. So */ float p16 = phase * n_stepseqsteps; int pstep = ((int)p16) & (n_stepseqsteps - 1); diff --git a/src/common/dsp/modulators/MSEGModulationHelper.cpp b/src/common/dsp/modulators/MSEGModulationHelper.cpp index 3d94230b288..d502d9cc47b 100644 --- a/src/common/dsp/modulators/MSEGModulationHelper.cpp +++ b/src/common/dsp/modulators/MSEGModulationHelper.cpp @@ -279,7 +279,7 @@ float valueAt(int ip, float fup, float df, MSEGStorage *ms, EvaluatorState *es, { /* There is a pathological case here where the deform is non-zero but very small * where this results in a floating point underflow. That is, if df is e1-7 then - * e^df - 1 is basically the last decimal place and you get floating point rounding + * e^df - 1 is basically the last decimal place and you get floating point rouding * quantization. So treat all deforms less than 1e-4 as zero. * * This is totally warranted because we work in float space. diff --git a/src/common/dsp/oscillators/ClassicOscillator.cpp b/src/common/dsp/oscillators/ClassicOscillator.cpp index af9546f66e6..f4d2818e2a2 100644 --- a/src/common/dsp/oscillators/ClassicOscillator.cpp +++ b/src/common/dsp/oscillators/ClassicOscillator.cpp @@ -97,14 +97,14 @@ ** ** Once we have committed to convolving an exact but differently aligned impulse stream into ** our sample output, though, we have the opportunity to exactly align the time of that -** impulse convolution with the moment between the samples when the actual impulse occurs. +** impulse convoultion with the moment between the samples when the actual impulse occurs. ** ** So the convolution has to manage a couple of dimensions of time. When we call ::convolute, ** remember, it is because we don't have enough buffer phase space computed for our current block. ** So ::convolute is filling a block in the "future" of our current pointer. That means we can ** actually use a slightly non-causal filter into the oscstate future. So, mechanically, ** we end up implementing: -** oscbuffer [i + futurelook] = sum(impulse change) * impulse[i] +** oscbuffer [i + futurelook] = sum(impulse chage) * impulse[i] ** ** Surge adds one last wrinkle, which is that impulse function depends on how far between a sample ** you are. The peak of the function should happen exactly at the point intra-sample. To do that it @@ -408,7 +408,7 @@ template void ClassicOscillator::convolute(int voice, bool stereo) ** Well the answer is that we want the time to be pushed around in Hz. So it turns out that ** 44100 * 2 / ( 440 * 8.175 ) =~ 24.2 and 24.2 / 16 = 1.447 which is almost how much *absolute is off. So - ** let's set the multiplier here so that the regtests exactly match the display frequency. + ** let's set the multiplier here so that the regtests exacty match the display frequency. *That is the ** frequency desired spread / 0.9443. 0.9443 is empirically determined by running the 2 *unison voices case diff --git a/src/common/dsp/oscillators/ModernOscillator.cpp b/src/common/dsp/oscillators/ModernOscillator.cpp index 700910fcd46..2d26c2b5816 100644 --- a/src/common/dsp/oscillators/ModernOscillator.cpp +++ b/src/common/dsp/oscillators/ModernOscillator.cpp @@ -107,8 +107,8 @@ * (u_i - 2 u_i-1 + u i-2 ) / dt^2. *But*, since i am calculating at i, we can either * think that that is second-order-accurate-in-dt and lagged by one sample or * first order accurate-in-dt and not lagged. It doesn't really matter. I also considered - * having the candidate phases be +1/0/-1 rather than 0/-1/-2 but that somehow felt - * a wee bit like cheating. Anyway, the difference is negligible. + * having the candidate phases be +1/0/-1 rather tha 0/-1/-2 but that somehow felt + * a wee bit like cheating. Anyway, the difference is negligble. * * Other than that, FM is obivous, sync runs two clocks and resets obviously, * and the rest is just mixing and lagging. All pretty obvious. @@ -254,7 +254,7 @@ void ModernOscillator::process_sblk(float pitch, float drift, bool stereo, float sBuff[s] = sawcub; /* - * Remember these ifs are now on template params so won't + * Remember these ifs are now on tempalte params so won't * eject branches */ if (subOctave) diff --git a/src/common/dsp/oscillators/SineOscillator.cpp b/src/common/dsp/oscillators/SineOscillator.cpp index d807d7276c4..0b9bb4152ea 100644 --- a/src/common/dsp/oscillators/SineOscillator.cpp +++ b/src/common/dsp/oscillators/SineOscillator.cpp @@ -18,10 +18,10 @@ #include /* - * Sine Oscillator Optimization Strategy + * Sine Oscilator Optimization Strategy * * With Surge 1.9, we undertook a bunch of work to optimize the sine oscillator runtime at high - * unison count with odd shapes. Basically at high unison we were doing large numbers of loops, + * unison count with odd shapes. Basicaly at high unison we were doing large numbers of loops, * branches and so forth, and not using any of the advantage you could get by realizing the paralle * structure of unison. So we fixed that. * @@ -61,7 +61,7 @@ * and into the DOCASE switch statement in process_block. Compile, run, test. * * 2. Then if that works, and you can code up your mode as an SSE function, remove that - * specialization and instead specialize the mode in the SSE-named function. + * specialization and instead specialize the mode in teh SSE-named function. * * Should all be pretty clear. */ diff --git a/src/common/dsp/oscillators/StringOscillator.cpp b/src/common/dsp/oscillators/StringOscillator.cpp index 8885f887b8b..6204d73b1d2 100644 --- a/src/common/dsp/oscillators/StringOscillator.cpp +++ b/src/common/dsp/oscillators/StringOscillator.cpp @@ -24,7 +24,7 @@ * * At init: * - Excite the delay line with an input. In 'chirp' mode this is only pre-play and - * in 'continuous' mode it is scaled by the amplitude during play + * in 'continous' mode it is scaled by the amplitude during play * * At runtime: * - run two delay lines seeded the same and take two taps, tap1 and tap2, @@ -169,7 +169,7 @@ void StringOscillator::init(float pitch, bool is_display, bool nzi) tap[1].startValue(pitchmult2_inv); t2level.startValue(0.5 * limit_range(localcopy[id_strbalance].f, -1.f, 1.f) + 0.5); - // we need a big prefill to support the delay line for FM + // we need a big prefill to supprot the delay line for FM auto prefill = (int)floor(10 * std::max(pitchmult_inv, pitchmult2_inv)); for (int i = 0; i < 2; ++i) diff --git a/src/common/dsp/utilities/DSPUtils.h b/src/common/dsp/utilities/DSPUtils.h index d192d81a68c..98220da0996 100644 --- a/src/common/dsp/utilities/DSPUtils.h +++ b/src/common/dsp/utilities/DSPUtils.h @@ -186,7 +186,7 @@ inline float lerp(float a, float b, float x) { return (1 - x) * a + x * b; } inline void trixpan( float &L, float &R, - float x) // panning that always lets both channels through unattenuated (separate hard-panning) + float x) // panning that always lets both channels through unattenuated (seperate hard-panning) { if (x < 0.f) { diff --git a/src/common/dsp/vembertech/lipol.h b/src/common/dsp/vembertech/lipol.h index a7dadbf8287..8a740a05e19 100644 --- a/src/common/dsp/vembertech/lipol.h +++ b/src/common/dsp/vembertech/lipol.h @@ -83,7 +83,7 @@ class lipol_ps void subtract_block(float *src, unsigned int nquads); void trixpan_blocks(float *L, float *R, float *dL, float *dR, unsigned int nquads); // panning that always lets both channels through - // unattenuated (separate hard-panning) + // unattenuated (seperate hard-panning) void multiply_block_to(float *src, float *dst, unsigned int nquads); void multiply_2_blocks(float *src1, float *src2, unsigned int nquads); void multiply_2_blocks_to(float *src1, float *src2, float *dst1, float *dst2, diff --git a/src/platform/CMakeLists.txt b/src/platform/CMakeLists.txt index 321e474a915..7021a9d1ade 100644 --- a/src/platform/CMakeLists.txt +++ b/src/platform/CMakeLists.txt @@ -1,12 +1,20 @@ # vi:set sw=2 et: project(surge-platform) +add_library(${PROJECT_NAME} + include/platform/Paths.h + src/Paths.cpp + ) if(APPLE) - add_library(${PROJECT_NAME} + target_sources(${PROJECT_NAME} PRIVATE macos/cpp17-aligned-new.cpp + unix/Paths.cpp ) elseif(WIN32) - add_library(${PROJECT_NAME} INTERFACE) + target_sources(${PROJECT_NAME} PRIVATE windows/Paths.cpp) elseif(UNIX) - add_library(${PROJECT_NAME} INTERFACE) + target_sources(${PROJECT_NAME} PRIVATE unix/Paths.cpp) + target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_DL_LIBS}) endif() +target_link_libraries(${PROJECT_NAME} PUBLIC surge::filesystem) +target_include_directories(${PROJECT_NAME} PUBLIC include) diff --git a/src/platform/include/platform/Paths.h b/src/platform/include/platform/Paths.h new file mode 100644 index 00000000000..4f2c725415d --- /dev/null +++ b/src/platform/include/platform/Paths.h @@ -0,0 +1,36 @@ +/* +** Surge Synthesizer is Free and Open Source Software +** +** Surge is made available under the Gnu General Public License, v3.0 +** https://www.gnu.org/licenses/gpl-3.0.en.html +** +** Copyright 2004-2021 by various individuals as described by the Git transaction log +** +** All source at: https://github.com/surge-synthesizer/surge.git +** +** Surge was a commercial product from 2004-2018, with Copyright and ownership +** in that period held by Claes Johanson at Vember Audio. Claes made Surge +** open source in September 2018. +*/ + +#pragma once + +#include "filesystem/import.h" + +namespace Surge::Paths +{ + +/// @return The path of the running Surge application / plugin itself. Equivalent to binaryPath(), +/// except on macOS, where it returns the bundle directory (.app, .component, ...) +fs::path appPath(); + +/// @return The path of the running Surge binary file itself (.exe, .dll, .so, ...) +fs::path binaryPath(); + +/// @return The current user's home directory (e.g. /home/user, /Users/user, C:\Users\user) +fs::path homePath(); + +/// @return The directory where the running Surge application / plugin is installed +inline fs::path installPath() { return appPath().parent_path(); } + +} // namespace Surge::Paths diff --git a/src/platform/src/Paths.cpp b/src/platform/src/Paths.cpp new file mode 100644 index 00000000000..3b2ea01ed7b --- /dev/null +++ b/src/platform/src/Paths.cpp @@ -0,0 +1,31 @@ +/* +** Surge Synthesizer is Free and Open Source Software +** +** Surge is made available under the Gnu General Public License, v3.0 +** https://www.gnu.org/licenses/gpl-3.0.en.html +** +** Copyright 2004-2021 by various individuals as described by the Git transaction log +** +** All source at: https://github.com/surge-synthesizer/surge.git +** +** Surge was a commercial product from 2004-2018, with Copyright and ownership +** in that period held by Claes Johanson at Vember Audio. Claes made Surge +** open source in September 2018. +*/ + +#include "platform/Paths.h" + +namespace Surge::Paths +{ + +fs::path appPath() +{ +#ifdef __APPLE__ + // FIXME: This is what the old code did. We can probably do better... + return binaryPath().parent_path().parent_path().parent_path(); +#else + return binaryPath(); +#endif +} + +} // namespace Surge::Paths diff --git a/src/platform/unix/Paths.cpp b/src/platform/unix/Paths.cpp new file mode 100644 index 00000000000..b9f601a8868 --- /dev/null +++ b/src/platform/unix/Paths.cpp @@ -0,0 +1,43 @@ +/* +** Surge Synthesizer is Free and Open Source Software +** +** Surge is made available under the Gnu General Public License, v3.0 +** https://www.gnu.org/licenses/gpl-3.0.en.html +** +** Copyright 2004-2021 by various individuals as described by the Git transaction log +** +** All source at: https://github.com/surge-synthesizer/surge.git +** +** Surge was a commercial product from 2004-2018, with Copyright and ownership +** in that period held by Claes Johanson at Vember Audio. Claes made Surge +** open source in September 2018. +*/ + +#include "platform/Paths.h" +#include +#include +#include + +namespace Surge::Paths +{ + +fs::path binaryPath() +{ + Dl_info info; + if (!dladdr(reinterpret_cast(&binaryPath), &info) || !info.dli_fname[0]) + { + // If dladdr(3) returns zero, dlerror(3) won't know why either + throw std::runtime_error{"Failed to retrieve shared object file name"}; + } + return fs::path{info.dli_fname}; +} + +fs::path homePath() +{ + const char *const path = std::getenv("HOME"); + if (!path || !path[0]) + throw std::runtime_error{"The environment variable HOME is unset or empty"}; + return fs::path{path}; +} + +} // namespace Surge::Paths diff --git a/src/platform/windows/Paths.cpp b/src/platform/windows/Paths.cpp new file mode 100644 index 00000000000..cc8c476c756 --- /dev/null +++ b/src/platform/windows/Paths.cpp @@ -0,0 +1,65 @@ +/* +** Surge Synthesizer is Free and Open Source Software +** +** Surge is made available under the Gnu General Public License, v3.0 +** https://www.gnu.org/licenses/gpl-3.0.en.html +** +** Copyright 2004-2021 by various individuals as described by the Git transaction log +** +** All source at: https://github.com/surge-synthesizer/surge.git +** +** Surge was a commercial product from 2004-2018, with Copyright and ownership +** in that period held by Claes Johanson at Vember Audio. Claes made Surge +** open source in September 2018. +*/ + +#include "platform/Paths.h" +#include +#include +#include + +namespace +{ + +fs::path knownFolderPath(REFKNOWNFOLDERID rfid) +{ + fs::path path; + PWSTR pathStr{}; + if (::SHGetKnownFolderPath(rfid, 0, nullptr, &pathStr) == S_OK) + path = pathStr; + ::CoTaskMemFree(pathStr); + if (path.empty()) + throw std::runtime_error{"Failed to retrieve known folder path"}; + return path; +} + +} // anonymous namespace + +namespace Surge::Paths +{ + +fs::path binaryPath() +{ + HMODULE hmodule; + if (!::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + reinterpret_cast(&binaryPath), &hmodule)) + { + throw std::system_error{int(::GetLastError()), std::system_category(), + "Failed to retrieve module handle"}; + } + + for (std::vector buf{MAX_PATH};; buf.resize(buf.size() * 2)) + { + const auto len = ::GetModuleFileNameW(hmodule, &buf[0], buf.size()); + if (!len) + throw std::system_error{int(::GetLastError()), std::system_category(), + "Failed to retrieve module file name"}; + if (len < buf.size()) + return fs::path{&buf[0]}; + } +} + +fs::path homePath() { return knownFolderPath(FOLDERID_Profile); } + +} // namespace Surge::Paths diff --git a/src/surge-fx/CMakeLists.txt b/src/surge-fx/CMakeLists.txt index e75aeb39d50..1370917cb2a 100644 --- a/src/surge-fx/CMakeLists.txt +++ b/src/surge-fx/CMakeLists.txt @@ -62,7 +62,9 @@ target_link_libraries(${PROJECT_NAME} PRIVATE juce::juce_audio_processors ) -clap_juce_extensions_plugin(TARGET surge-fx - CLAP_ID "org.surge-synth-team.surge-xt-fx") +if (CLAP_JUCE_EXTENSIONS_ROOT) + clap_juce_extensions_plugin(TARGET surge-fx + CLAP_ID "org.surge-synth-team.surge-xt-fx") +endif() surge_juce_package(${PROJECT_NAME} "Surge XT Effects") diff --git a/src/surge-fx/SurgeFXProcessor.cpp b/src/surge-fx/SurgeFXProcessor.cpp index 1d62f38c583..aa76a1e67b7 100644 --- a/src/surge-fx/SurgeFXProcessor.cpp +++ b/src/surge-fx/SurgeFXProcessor.cpp @@ -292,7 +292,7 @@ void SurgefxAudioProcessor::processBlock(juce::AudioBuffer &buffer, output_position = 0; } - if (output_position >= 0 && output_position < BLOCK_SIZE) // that < should never happen + if (output_position >= 0 && output_position < BLOCK_SIZE) // that < shoudl never happen { outL[smp] = output_buffer[0][output_position]; outR[smp] = output_buffer[1][output_position]; diff --git a/src/surge-python/surgepy.cpp b/src/surge-python/surgepy.cpp index eae69f2c8a3..32f194ed125 100644 --- a/src/surge-python/surgepy.cpp +++ b/src/surge-python/surgepy.cpp @@ -23,7 +23,7 @@ static std::mutex spysetup_mutex; /* * The way we've decided to expose to python is through some wrapper objects - * which give us the control gorup / control group entry / param hierarchy. + * which give us the control gorup / control group entry / param heirarchy. * So here's some small helper objects */ diff --git a/src/surge-testrunner/UnitTestsINFRA.cpp b/src/surge-testrunner/UnitTestsINFRA.cpp index 5b856014b96..6ba06b8132a 100644 --- a/src/surge-testrunner/UnitTestsINFRA.cpp +++ b/src/surge-testrunner/UnitTestsINFRA.cpp @@ -6,8 +6,6 @@ #include "QuadFilterUnit.h" #include "MemoryPool.h" -#include "strnatcmp.h" - #include "catch2/catch2.hpp" inline size_t align_diff(const void *ptr, std::uintptr_t alignment) noexcept @@ -83,7 +81,7 @@ TEST_CASE("QFU is Aligned", "[infra]") } } -// A is just a test index to separate the classes +// A is just a test index to separate the calsses template struct CountAlloc { CountAlloc() @@ -142,56 +140,4 @@ TEST_CASE("Memory Pool Works", "[infra]") REQUIRE(CountAlloc<3>::alloc == 160); REQUIRE(CountAlloc<3>::ct == 0); } -} - -TEST_CASE("strnatcmp with spaces", "[infra]") -{ - SECTION("Basic Compare") - { - REQUIRE(strnatcmp("foo", "bar") == 1); - REQUIRE(strnatcmp("bar", "foo") == -1); - REQUIRE(strnatcmp("bar", "bar") == 0); - } - - SECTION("Number Compare") - { - REQUIRE(strnatcmp("1 foo", "2 foo") == -1); - REQUIRE(strnatcmp("1 foo", "11 foo") == -1); - REQUIRE(strnatcmp("1 foo", "91 foo") == -1); - REQUIRE(strnatcmp("01 foo", "91 foo") == -1); - REQUIRE(strnatcmp("91 foo", "1 foo") == 1); - REQUIRE(strnatcmp("91 foo", "01 foo") == 1); - REQUIRE(strnatcmp("91 foo", "001 foo") == 1); - REQUIRE(strnatcmp("1 foo", "112 foo") == -1); - REQUIRE(strnatcmp("91 foo", "112 foo") == -1); - REQUIRE(strnatcmp("112 foo", "91 foo") == 1); - REQUIRE(strnatcmp("01 foo", "2 foo") == -1); - REQUIRE(strnatcmp("001 foo", "2 foo") == -1); - REQUIRE(strnatcmp("001 foo", "002 foo") == -1); - // Fix these one day - // REQUIRE(strnatcmp("01 foo", "002 foo") == -1); - // REQUIRE(strnatcmp("1 foo", "002 foo") == -1); - // REQUIRE(strnatcmp("1 foo", "02 foo") == -1); - } - - SECTION("Spaces vs Letters") - { - REQUIRE(strnatcmp("hello", "zebra") == -1); - REQUIRE(strnatcmp("hello ", "zebra") == -1); - REQUIRE(strnatcmp(" hello", "zebra") == -1); - REQUIRE(strnatcmp("hello", " zebra") == -1); - REQUIRE(strnatcmp("hello", "zebra ") == -1); - REQUIRE(strnatcmp("hello", "z") == -1); - REQUIRE(strnatcmp("hello", "z ") == -1); - REQUIRE(strnatcmp("hello", " z") == -1); - REQUIRE(strnatcmp(" hello", "z") == -1); - REQUIRE(strnatcmp("hello ", "z") == -1); - } - - SECTION("Central Spaces") - { - REQUIRE(strnatcmp("Spa Day", "SpaDay") == -1); - REQUIRE(strnatcmp("SpaDay", "Spa Day") == 1); - } - SECTION("Doubled Spaces") { REQUIRE(strnatcmp("Spa Day", "Spa Day") == 0); } } \ No newline at end of file diff --git a/src/surge-testrunner/UnitTestsMOD.cpp b/src/surge-testrunner/UnitTestsMOD.cpp index decc449d631..5b7d8b0c32a 100644 --- a/src/surge-testrunner/UnitTestsMOD.cpp +++ b/src/surge-testrunner/UnitTestsMOD.cpp @@ -937,8 +937,8 @@ TEST_CASE("Keytrack Morph", "[mod]") { surge->process(); /* - * FIXME: Make this an assertive test. What we are really checking is, is l_shape 3.33 - * inside the oscillator? But there's no easy way to assert that so just leave the test + * FIXME: Make this an assertive test. What we are really checking is is l_shape 3.33 + * inside the oscillator but there's no easy way to assert that so just leave the test * here as a debugging harness around issue 3046 */ } diff --git a/src/surge-testrunner/UnitTestsTUN.cpp b/src/surge-testrunner/UnitTestsTUN.cpp index 07915f1e6e1..6805c82c571 100644 --- a/src/surge-testrunner/UnitTestsTUN.cpp +++ b/src/surge-testrunner/UnitTestsTUN.cpp @@ -860,7 +860,7 @@ TEST_CASE("Mapping below and outside of count") } } - SECTION("A lot below with 6ns") + SECTION("A lot below witn 6ns") { auto surge = Surge::Headless::createSurge(44100); surge->storage.tuningApplicationMode = SurgeStorage::RETUNE_ALL; @@ -900,7 +900,7 @@ TEST_CASE("Mapping below and outside of count") } } - SECTION("A lot below with ED3-17") + SECTION("A lot below witn ED3-17") { auto surge = Surge::Headless::createSurge(44100); surge->storage.tuningApplicationMode = SurgeStorage::RETUNE_ALL; @@ -1039,7 +1039,7 @@ TEST_CASE("Ignoring Tuning Tables are Correct", "[dsp][tun]") } } - SECTION("Ignoring if retuned compares with untuned") + SECTION("Ignoring in retuned compares with untuned") { auto surge = surgeOnSine(); auto surgeTuned = surgeOnSine(); diff --git a/src/surge-testrunner/main.cpp b/src/surge-testrunner/main.cpp index 2967c8dc153..5b160c61c86 100644 --- a/src/surge-testrunner/main.cpp +++ b/src/surge-testrunner/main.cpp @@ -66,7 +66,7 @@ int main(int argc, char **argv) << " --non-test --filter-analyzer ft fst # analyze filter type/subtype for " "response\n" << "\n" - << "If you exclude the `--non-test` argument, standard catch2 arguments, below, " + << "If you exlude the `--non-test` argument, standard catch2 arguments, below, " "apply\n\n"; } diff --git a/src/surge-xt/CMakeLists.txt b/src/surge-xt/CMakeLists.txt index 232595c3e7b..64abc32e98c 100644 --- a/src/surge-xt/CMakeLists.txt +++ b/src/surge-xt/CMakeLists.txt @@ -50,9 +50,11 @@ juce_add_plugin(${PROJECT_NAME} FORMATS ${SURGE_JUCE_FORMATS} ) -clap_juce_extensions_plugin(TARGET surge-xt - CLAP_ID "org.surge-synth-team.surge-xt") -target_sources(${PROJECT_NAME}_CLAP PRIVATE plugin_type_extensions/SurgeSynthClapExtensions.cpp) +if (CLAP_JUCE_EXTENSIONS_ROOT) + clap_juce_extensions_plugin(TARGET surge-xt + CLAP_ID "org.surge-synth-team.surge-xt") + target_sources(${PROJECT_NAME}_CLAP PRIVATE plugin_type_extensions/SurgeSynthClapExtensions.cpp) +endif() if(JUCE_ASIO_SUPPORT) target_compile_definitions(${PROJECT_NAME} PUBLIC JUCE_ASIO=1) diff --git a/src/surge-xt/gui/SkinSupport.cpp b/src/surge-xt/gui/SkinSupport.cpp index 57c011f9282..07894f52bea 100644 --- a/src/surge-xt/gui/SkinSupport.cpp +++ b/src/surge-xt/gui/SkinSupport.cpp @@ -133,7 +133,7 @@ void SkinDB::rescanForSkins(SurgeStorage *storage) catch (const fs::filesystem_error &e) { // This will give us a broken skin but no need to tell the users - FIXMEERROR << "Unable to traverse for skins in user directory: " << e.what(); + FIXMEERROR << "Unable to travese for skins in user directory: " << e.what(); } for (auto &p : alldirs) @@ -561,9 +561,8 @@ bool Skin::reloadSkin(std::shared_ptr bitmapStore) validKids = false; // for( auto kk : k.second ) // std::cout << _D(kk.first) << _D(kk.second) << std::endl; - FIXMEERROR - << "Each subchild of a multi-image must contain a zoom-level and " - "resource"; + FIXMEERROR << "Each subchild of a multi-image must ontain a zoom-level and " + "resource"; break; } else if (k.second["zoom-level"] == "100") @@ -937,8 +936,8 @@ bool Skin::recursiveGroupParse(ControlGroup::ptr_t parent, TiXmlElement *control } /* - * Per long discussion Feb 20 on discord, the expectation in the skin engine - * is that you are overriding defaults *except* parent groups in the XML will reset + * Per long discussion Feb 20 on discord, the expetation inthe skin engine + * is that you are overriding defaults *except* parent groups in the XML wil lreset * your default position to the origin. So if we *don't* specify an x/y and * *are* in a user specified group, reset the control default before we apply * the XML and offsets @@ -1289,7 +1288,7 @@ void Surge::GUI::Skin::resolveBaseParentOffsets(Skin::Control::ptr_t c) { if (c->parentResolved) return; - // When we enter here, all the objects will have been created by the loop above + // When we enter here, all the objects will ahve been created by the loop above if (c->allprops.find("base_parent") != c->allprops.end()) { // std::cout << "Control Parent " << _D(c->x) << _D(c->y) << std::endl; diff --git a/src/surge-xt/gui/SkinSupport.h b/src/surge-xt/gui/SkinSupport.h index 76e79d0936b..92498d3adf8 100644 --- a/src/surge-xt/gui/SkinSupport.h +++ b/src/surge-xt/gui/SkinSupport.h @@ -27,7 +27,7 @@ ** Support for rudimentary skinning in Surge ** ** SkinSupport provides a pair of classes, a SkinManager and a SkinDB -** The SkinManager singleton loads and applies the SkinDB to various places as +** The SkinManager singleton loads and applys the SkinDB to various places as ** appropriate. The SkinDB has all the information you would need ** to skin yourself, and answers various queries. */ @@ -261,7 +261,7 @@ class Skin auto stringNames = c->defaultComponent.payload->propertyNamesMap[pkey]; /* - ** Traverse class hierarchy looking for value + ** Traverse class heirarchy looking for value */ for (auto const &key : stringNames) diff --git a/src/surge-xt/gui/SurgeGUIEditor.cpp b/src/surge-xt/gui/SurgeGUIEditor.cpp index a13c8377726..762f917ac3b 100644 --- a/src/surge-xt/gui/SurgeGUIEditor.cpp +++ b/src/surge-xt/gui/SurgeGUIEditor.cpp @@ -564,12 +564,11 @@ void SurgeGUIEditor::idle() std::ostringstream oss; oss << "Loading patch " << synth->patchid_queue - << " has not occurred after 200 idle cycles. This means that the audio system" - << " is delayed while loading many patches in a row. The audio system has to be" - << " running in order to load Surge patches. If the audio system is working," + << " has not occured after 200 idle cycles. This means that the audio engine" + << " is delayed while loading many patches in a row. The audio engine has to be" + << " running in order to load Surge XT patches. If the audio engine is working," " you can probably ignore this message and continue once Surge XT catches " "up."; - synth->storage.reportError(oss.str(), "Patch Loading Error"); } } @@ -4810,7 +4809,6 @@ SurgeGUIEditor::layoutComponentForSkin(std::shared_ptr( juceSkinComponents[skinCtrl->sessionid].get()); } - if (skinCtrl->defaultComponent == Surge::Skin::Components::MultiSwitch) { auto rect = juce::Rectangle(skinCtrl->x, skinCtrl->y, skinCtrl->w, skinCtrl->h); @@ -4874,8 +4872,6 @@ SurgeGUIEditor::layoutComponentForSkin(std::shared_ptrsetDeactivated(p->appears_deactivated()); - auto fval = p->get_value_f01(); if (p->ctrltype == ct_scenemode) @@ -4914,14 +4910,22 @@ SurgeGUIEditor::layoutComponentForSkin(std::shared_ptrgetControlGroupLayer(cg), *hsw); @@ -4949,10 +4953,9 @@ SurgeGUIEditor::layoutComponentForSkin(std::shared_ptrdefaultComponent == Surge::Skin::Components::Switch) { auto rect = juce::Rectangle(skinCtrl->x, skinCtrl->y, skinCtrl->w, skinCtrl->h); @@ -4962,7 +4965,6 @@ SurgeGUIEditor::layoutComponentForSkin(std::shared_ptr(skinCtrl->sessionid); hsw->setStorage(&(synth->storage)); - if (p) { addAndMakeVisibleWithTrackingInCG(p->ctrlgroup, *hsw); @@ -5004,11 +5006,9 @@ SurgeGUIEditor::layoutComponentForSkin(std::shared_ptr= 0) nonmod_param[paramIndex] = hsw.get(); - if (p) { hsw->setValue(p->get_value_f01()); - hsw->setDeactivated(p->appears_deactivated()); // Carry over this filter type special case from the default control path if (p->ctrltype == ct_filtersubtype) @@ -5044,7 +5044,6 @@ SurgeGUIEditor::layoutComponentForSkin(std::shared_ptrsessionid].get()); } } - if (skinCtrl->defaultComponent == Surge::Skin::Components::LFODisplay) { if (!p) @@ -5121,7 +5120,6 @@ SurgeGUIEditor::layoutComponentForSkin(std::shared_ptrdefaultComponent == Surge::Skin::Components::FxMenu) { if (!fxMenu) @@ -5242,7 +5240,6 @@ SurgeGUIEditor::layoutComponentForSkin(std::shared_ptrdefaultComponent == Surge::Skin::Components::FilterSelector) { // Obviously exposing this widget as a controllable widget would be better @@ -5340,7 +5337,6 @@ SurgeGUIEditor::layoutComponentForSkin(std::shared_ptr( juceSkinComponents[skinCtrl->sessionid].get()); } - if (skinCtrl->defaultComponent == Surge::Skin::Components::WaveShaperSelector) { // Obviously exposing this widget as a controllable widget would be better @@ -5374,11 +5370,9 @@ SurgeGUIEditor::layoutComponentForSkin(std::shared_ptr(waveshaperSelector.get()); } - if (skinCtrl->ultimateparentclassname != Surge::GUI::NoneClassName) - std::cout << "Unable to make control with UPC " << skinCtrl->ultimateparentclassname + std::cout << "Unable to make control with upc " << skinCtrl->ultimateparentclassname << std::endl; - return nullptr; } diff --git a/src/surge-xt/gui/SurgeGUIEditorHtmlGenerators.cpp b/src/surge-xt/gui/SurgeGUIEditorHtmlGenerators.cpp index 423585b7a3f..fb38d9d7e9a 100644 --- a/src/surge-xt/gui/SurgeGUIEditorHtmlGenerators.cpp +++ b/src/surge-xt/gui/SurgeGUIEditorHtmlGenerators.cpp @@ -241,7 +241,7 @@ std::string SurgeGUIEditor::tuningToHtml() if (synth->storage.currentMapping.count > 48) { - htmls << "Surge XT only displays interval matrices for scales lower than 48 in length" + htmls << "Surge XT only displays inverval matrices for scales lower than 48 in length" << std::endl; } else diff --git a/src/surge-xt/gui/SurgeGUIEditorValueCallbacks.cpp b/src/surge-xt/gui/SurgeGUIEditorValueCallbacks.cpp index 27ee8cf6b74..260540d7bfe 100644 --- a/src/surge-xt/gui/SurgeGUIEditorValueCallbacks.cpp +++ b/src/surge-xt/gui/SurgeGUIEditorValueCallbacks.cpp @@ -908,7 +908,7 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c 100 * cms->get_output(0)); contextMenu.addItem(vtxt, [this, bvf, modsource]() { promptForUserValueEntry(nullptr, bvf, modsource, - 0, // controllers aren't per scene + 0, // controllers arent per scene 0); // controllers aren't indexed }); @@ -1643,24 +1643,7 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c { switch (p->ctrltype) { - case ct_freq_hpf: - { - contextMenu.addSeparator(); - - contextMenu.addSectionHeader("SLOPE"); - for (int i = 0; i < synth->n_hpBQ; i++) - { - std::string title = fmt::format("{:d} dB/oct", 12 * (i + 1)); - - bool isChecked = p->deform_type == i; - - contextMenu.addItem(title, true, isChecked, - [this, p, i]() { p->deform_type = i; }); - } - - break; - } case ct_lfodeform: { auto q = modsource_editor[current_scene]; @@ -1675,7 +1658,8 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c for (int i = 0; i < lt_num_deforms[lfodata->shape.val.i]; i++) { - std::string title = fmt::format("Type {:d}", (i + 1)); + char title[32]; + sprintf(title, "Type %d", (i + 1)); bool isChecked = p->deform_type == i; @@ -1837,7 +1821,7 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c txt = "Randomize Initial Drift Phase"; break; case ct_twist_aux_mix: - txt = "Pan Main and Auxiliary Signals"; + txt = "Pan Main and Auxilliary Signals"; break; case ct_countedset_percent_extendable: txt = "Continuous Morph"; @@ -2306,7 +2290,7 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c ** This code resets you to default if you double-click on control, ** but on the LFO type widget this is undesirable; it means if you accidentally ** Control-click on step sequencer, say, you go back to Sine and lose your - ** edits. So suppress it! + ** edits. So supress it! */ break; case ct_freq_audible_with_tunability: diff --git a/src/surge-xt/gui/SurgeJUCELookAndFeel.cpp b/src/surge-xt/gui/SurgeJUCELookAndFeel.cpp index f50f95d3873..0d46e0252bc 100644 --- a/src/surge-xt/gui/SurgeJUCELookAndFeel.cpp +++ b/src/surge-xt/gui/SurgeJUCELookAndFeel.cpp @@ -292,7 +292,7 @@ Button *SurgeJUCELookAndFeel::createDocumentWindowButton(int buttonType) return nullptr; } -// overridden here just to make the shortcut text same size as normal menu entry text +// overriden here just to make the shortcut text same size as normal menu entry text void SurgeJUCELookAndFeel::drawPopupMenuItem(Graphics &g, const Rectangle &area, const bool isSeparator, const bool isActive, const bool isHighlighted, const bool isTicked, diff --git a/src/surge-xt/gui/overlays/AboutScreen.cpp b/src/surge-xt/gui/overlays/AboutScreen.cpp index e19aab639a3..910bdcaa343 100644 --- a/src/surge-xt/gui/overlays/AboutScreen.cpp +++ b/src/surge-xt/gui/overlays/AboutScreen.cpp @@ -20,7 +20,7 @@ #include "version.h" #include "RuntimeFont.h" #include "SurgeImage.h" -#include "sst/plugininfra/paths.h" +#include "platform/Paths.h" #include namespace Surge @@ -193,8 +193,8 @@ void AboutScreen::populateData() lowerLeft.emplace_back("", "", ""); - auto apppath = sst::plugininfra::paths::sharedLibraryBinaryPath(); - lowerLeft.emplace_back("Executable:", apppath.u8string(), apppath.parent_path().u8string()); + lowerLeft.emplace_back("Executable:", Paths::appPath().u8string(), + Paths::appPath().parent_path().u8string()); lowerLeft.emplace_back("Factory Data:", storage->datapath.u8string(), storage->datapath.u8string()); lowerLeft.emplace_back("User Data:", storage->userDataPath.u8string(), diff --git a/src/surge-xt/gui/overlays/MSEGEditor.cpp b/src/surge-xt/gui/overlays/MSEGEditor.cpp index f37d661b992..7159be5b4ae 100644 --- a/src/surge-xt/gui/overlays/MSEGEditor.cpp +++ b/src/surge-xt/gui/overlays/MSEGEditor.cpp @@ -155,7 +155,7 @@ struct MSEGCanvas : public juce::Component, public Surge::GUI::SkinConsumingComp enum Type { MOUSABLE_NODE, - INACTIVE_NODE, // To keep the array the same size add dummies when you suppress controls + INACTIVE_NODE, // To keep the array the same size add dummies when you supress controls LOOPMARKER } type; @@ -1195,7 +1195,7 @@ struct MSEGCanvas : public juce::Component, public Surge::GUI::SkinConsumingComp v = valpx(v); vdef = valpx(vdef); // Brownian doesn't deform and the second display is confusing since it is - // independently random + // indepdently random if (es.lastEval >= 0 && es.lastEval <= ms->n_activeSegments - 1 && ms->segments[es.lastEval].type == MSEGStorage::segment::Type::BROWNIAN) vdef = v; @@ -1410,9 +1410,9 @@ struct MSEGCanvas : public juce::Component, public Surge::GUI::SkinConsumingComp if (h.type == hotzone::LOOPMARKER) { /* - * OK the loop marker suppression is a wee bit complicated + * OK the loop marker supression is a wee bit complicated * If the end is at 0, it draws over the axis; if the start is at end similar - * so handle the cases differently. Remember this is because the 'marker' + * so handle the cases differently. Remeber this is because the 'marker' * of the start graphic is the left edge |< and the right end is >| */ if (h.zoneSubType == hotzone::LOOP_START) diff --git a/src/surge-xt/gui/overlays/PatchDBViewer.cpp b/src/surge-xt/gui/overlays/PatchDBViewer.cpp index 8999e29c4a6..0da3a14bb5a 100644 --- a/src/surge-xt/gui/overlays/PatchDBViewer.cpp +++ b/src/surge-xt/gui/overlays/PatchDBViewer.cpp @@ -289,7 +289,7 @@ class PatchDBSQLTableModel : public juce::TableListBoxModel void paintCell(juce::Graphics &g, int rowNumber, int columnId, int width, int height, bool rowIsSelected) override { - // FIXME - make sure the condition this is handling is handled everywhere consistently + // FIXME - make sure the codition this is handling is handled everywhere consistently if (rowNumber >= data.size()) { return; @@ -317,7 +317,7 @@ class PatchDBSQLTableModel : public juce::TableListBoxModel void cellDoubleClicked(int rowNumber, int columnId, const juce::MouseEvent &event) override { - // FIXME - make sure the condition this is handling is handled everywhere consistently + // FIXME - make sure the codition this is handling is handled everywhere consistently if (rowNumber >= data.size()) { return; diff --git a/src/surge-xt/gui/overlays/TuningOverlays.cpp b/src/surge-xt/gui/overlays/TuningOverlays.cpp index 9af8d694f3c..07a57a54b0b 100644 --- a/src/surge-xt/gui/overlays/TuningOverlays.cpp +++ b/src/surge-xt/gui/overlays/TuningOverlays.cpp @@ -269,7 +269,7 @@ class InfiniteKnob : public juce::Component, public Surge::GUI::SkinConsumingCom speed = speed / 10; } - // This is calibrated to give us reasonable speed on a 0-1 basis from the slider + // This is callibrated to give us reasonable speed on a 0-1 basis from the slider // but in this widget '1' is the small motion so speed it up some speed *= 30; @@ -1452,7 +1452,7 @@ void RadialScaleGraph::mouseWheelMove(const juce::MouseEvent &event, speed = speed / 10; } - // This is calibrated to give us reasonable speed on a 0-1 basis from the slider + // This is callibrated to give us reasonable speed on a 0-1 basis from the slider // but in this widget '1' is the small motion so speed it up some auto dr = speed * delta; diff --git a/src/surge-xt/gui/widgets/ModulatableControlInterface.h b/src/surge-xt/gui/widgets/ModulatableControlInterface.h index 7060de11060..4913d9367d1 100644 --- a/src/surge-xt/gui/widgets/ModulatableControlInterface.h +++ b/src/surge-xt/gui/widgets/ModulatableControlInterface.h @@ -118,7 +118,7 @@ struct ModulatableControlInterface virtual float getModValue() const { return modValue; } float modValue{0.f}; - /* Deactivation can occur by a function or by a value */ + /* Deativation can occur by a function or by a value */ virtual void setDeactivatedFn(std::function f) { hasDeactivatedFn = true; diff --git a/src/surge-xt/gui/widgets/ModulatableSlider.h b/src/surge-xt/gui/widgets/ModulatableSlider.h index 8d25090b4ca..cdade7bb8f2 100644 --- a/src/surge-xt/gui/widgets/ModulatableSlider.h +++ b/src/surge-xt/gui/widgets/ModulatableSlider.h @@ -152,7 +152,7 @@ struct ModulatableSlider : public juce::Component, float barFM0X{0}, barFM0Y{0}, barFMNX{0}, barFMNY{0}; float handleX0{0}, handleY0{0}; - // how far logically do we move in tray space for our current state + // how far logically do we move in tray space for our curent state int trayTypeX{0}, trayTypeY{0}; // How far do we move in the image to make the handle image be the mod float modHandleX{0}; diff --git a/src/surge-xt/gui/widgets/MultiSwitch.cpp b/src/surge-xt/gui/widgets/MultiSwitch.cpp index 8d7dc9492d3..d59c24c73bf 100644 --- a/src/surge-xt/gui/widgets/MultiSwitch.cpp +++ b/src/surge-xt/gui/widgets/MultiSwitch.cpp @@ -40,15 +40,8 @@ void MultiSwitch::paint(juce::Graphics &g) auto y = -valueToOff(value) * heightOfOneImage; auto t = juce::AffineTransform().translated(0, y); - float activationOpacity = 1.0; - - if (isDeactivated) - { - activationOpacity = 0.5; - } - g.reduceClipRegion(getLocalBounds()); - switchD->draw(g, activationOpacity, t); + switchD->draw(g, 1.0, t); if (isHovered) { @@ -56,14 +49,14 @@ void MultiSwitch::paint(juce::Graphics &g) if (iv == hoverSelection && hoverOnSwitchD) { - hoverOnSwitchD->draw(g, activationOpacity, t); + hoverOnSwitchD->draw(g, 1.0, t); } else if (hoverSwitchD) { auto y2 = hoverSelection + frameOffset; auto t2 = juce::AffineTransform().translated(0, -y2 * heightOfOneImage); - hoverSwitchD->draw(g, activationOpacity, t2); + hoverSwitchD->draw(g, 1.0, t2); } } } diff --git a/src/surge-xt/gui/widgets/MultiSwitch.h b/src/surge-xt/gui/widgets/MultiSwitch.h index de5ed9d463a..2c562c5542d 100644 --- a/src/surge-xt/gui/widgets/MultiSwitch.h +++ b/src/surge-xt/gui/widgets/MultiSwitch.h @@ -110,9 +110,6 @@ struct MultiSwitch : public juce::Component, void updateAccessibleStateOnUserValueChange() override; std::unique_ptr createAccessibilityHandler() override; - bool isDeactivated{false}; - void setDeactivated(bool b) { isDeactivated = b; } - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MultiSwitch); }; diff --git a/src/surge-xt/gui/widgets/Switch.cpp b/src/surge-xt/gui/widgets/Switch.cpp index ff6f8e60650..d80dae7458f 100644 --- a/src/surge-xt/gui/widgets/Switch.cpp +++ b/src/surge-xt/gui/widgets/Switch.cpp @@ -41,21 +41,14 @@ void Switch::paint(juce::Graphics &g) y = -getIntegerValue() * getLocalBounds().getHeight(); } - float activationOpacity = 1.0; - - if (isDeactivated) - { - activationOpacity = 0.35; - } - auto t = juce::AffineTransform().translated(0, y); g.reduceClipRegion(getLocalBounds()); - switchD->draw(g, activationOpacity, t); + switchD->draw(g, 1.0, t); if (isHovered && hoverSwitchD) { - hoverSwitchD->draw(g, activationOpacity, t); + hoverSwitchD->draw(g, 1.0, t); } } diff --git a/src/surge-xt/gui/widgets/Switch.h b/src/surge-xt/gui/widgets/Switch.h index f061c71080f..d82dd6a9099 100644 --- a/src/surge-xt/gui/widgets/Switch.h +++ b/src/surge-xt/gui/widgets/Switch.h @@ -109,9 +109,6 @@ struct Switch : public juce::Component, public WidgetBaseMixin std::unique_ptr createAccessibilityHandler() override; - bool isDeactivated{false}; - void setDeactivated(bool b) { isDeactivated = b; } - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Switch); }; } // namespace Widgets diff --git a/src/surge-xt/gui/widgets/VerticalLabel.h b/src/surge-xt/gui/widgets/VerticalLabel.h index 2ed80dffe7a..cee2a06cfff 100644 --- a/src/surge-xt/gui/widgets/VerticalLabel.h +++ b/src/surge-xt/gui/widgets/VerticalLabel.h @@ -25,7 +25,7 @@ namespace Surge namespace Widgets { /* - * This is a pure play juce component which is referred to as such so doesn't + * This is a pure play juce component which is refered to as such so doesn't * need any fo the EFVG and Mixin stuff to interact with the value callback mechanism */ struct VerticalLabel : public juce::Component diff --git a/src/surge-xt/gui/widgets/WidgetBaseMixin.h b/src/surge-xt/gui/widgets/WidgetBaseMixin.h index a5ecac147c7..07e52dbb59c 100644 --- a/src/surge-xt/gui/widgets/WidgetBaseMixin.h +++ b/src/surge-xt/gui/widgets/WidgetBaseMixin.h @@ -96,7 +96,7 @@ struct WidgetBaseMixin : public Surge::GUI::SkinConsumingComponent, /* * So what the heck is this you may ask? Well when juce shows the info window on the * very first go round, since it is a hierarchy change, juce sends us a zero-distance - * mouse moved event. So we need to make sure, in the case of a start and only a start, + * mouse moved event. So we need ot make sure, in the case of a start and only a start, * that if we get two in a row they are from different places. See #5487 */ if (place == SurgeGUIEditor::InfoQAction::START) diff --git a/src/surge-xt/gui/widgets/XMLConfiguredMenus.h b/src/surge-xt/gui/widgets/XMLConfiguredMenus.h index f809c555f94..8a69db4195b 100644 --- a/src/surge-xt/gui/widgets/XMLConfiguredMenus.h +++ b/src/surge-xt/gui/widgets/XMLConfiguredMenus.h @@ -72,7 +72,7 @@ struct XMLMenuPopulator bool hasColumnBreak{false}; /* - * I know this isn't very generalized and I could template it and subclass + * I knwo this isn't very generalized and I could template it and subclass * and use this for N other controls. But I wont */ Surge::Storage::FxUserPreset::Preset fxPreset;