From e485fac8ed8ac53b4f544b841f761094e42299db Mon Sep 17 00:00:00 2001 From: ThorstenB Date: Thu, 16 Nov 2017 21:38:50 +0100 Subject: [PATCH 01/18] Provide polar earth radius as a simgear constant. --- simgear/constants.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/simgear/constants.h b/simgear/constants.h index 173d664a..316fa7f5 100644 --- a/simgear/constants.h +++ b/simgear/constants.h @@ -95,7 +95,7 @@ const float SG_RADIANS_TO_DEGREES = 180.0f / SG_PI; /** Value of earth radius from LaRCsim (ft) */ #define SG_EQUATORIAL_RADIUS_FT 20925650. -/** Value of earth radius from LaRCsim (meter) */ +/** Value of equatorial earth radius from LaRCsim (meter) */ #define SG_EQUATORIAL_RADIUS_M 6378138.12 /** Radius squared (ft) */ @@ -104,6 +104,8 @@ const float SG_RADIANS_TO_DEGREES = 180.0f / SG_PI; /** Radius squared (meter) */ #define SG_EQ_RAD_SQUARE_M 40680645877797.1344 +/** Value of WGS84 polar earth radius (meter) */ +#define SG_POLAR_RADIUS_M 6356752.3142451794975639668 // Physical Constants, SI From 1310092c0ca3c05c3b10555a4653130900a40cfb Mon Sep 17 00:00:00 2001 From: Florent Rougon Date: Sat, 18 Nov 2017 08:01:44 +0100 Subject: [PATCH 02/18] SGPath: enable move operations This is done by simply not user-defining the copy constructor, copy-assignment operator and destructor. See [1] for more info. [1] http://accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf For the benchmark below (compiled with the next commit to allow sorting SGPath instances), on Linux amd64 with g++ 6.3.0, I observe that enabling SGPath move operations with this commit increases the performance by 31% or 28% respectively, depending on whether I use this: // Typical code that creates a data structure in several steps and // benefits from move operations (the std::move() does nothing when // running the test with move operations disabled: a copy is made). auto p = SGPath::fromUtf8(randomString(0, 30)); v.emplace_back(std::move(p)); or that: v.emplace_back(randomString(0, 30)) for the initialization code. Now the benchmark code: using std::string; static std::default_random_engine randomNumbersGenerator; // Utility function: generate a random string whose length is in the // [minLen, maxLen] range. string randomString(string::size_type minLen, string::size_type maxLen) { std::uniform_int_distribution sLenDist(minLen, maxLen); std::uniform_int_distribution byteDist(0, 255); auto randomByte = std::bind(byteDist, randomNumbersGenerator); string::size_type len = sLenDist(randomNumbersGenerator); string str; while (str.size() < len) { str += std::char_traits::to_char_type(randomByte()); } return str; } // The test function, run with nbIterations = 500000, minSize = 0 and // maxSize = 200 to obtain the figures given above. void SGPath_perfTest(std::size_t nbIterations, std::size_t minSize, std::size_t maxSize) { std::uniform_int_distribution sizeDist(minSize, maxSize); auto randomSize = std::bind(sizeDist, randomNumbersGenerator); std::chrono::time_point start, end; start = std::chrono::system_clock::now(); vector v; for (std::size_t i=0; i < nbIterations; i++) { v = vector{}; // start anew for (std::size_t j=0; j < randomSize(); j++) { v.emplace_back(randomString(0, 30)); } std::shuffle(v.begin(), v.end(), randomNumbersGenerator); std::sort(v.begin(), v.end()); } end = std::chrono::system_clock::now(); std::chrono::duration elapsedSecs = end - start; std::cout << elapsedSecs.count() << "\n"; // duration in seconds } --- simgear/misc/sg_path.cxx | 38 -------------------------------------- simgear/misc/sg_path.hxx | 8 -------- 2 files changed, 46 deletions(-) diff --git a/simgear/misc/sg_path.cxx b/simgear/misc/sg_path.cxx index 05af794f..31f84bc7 100644 --- a/simgear/misc/sg_path.cxx +++ b/simgear/misc/sg_path.cxx @@ -240,44 +240,6 @@ SGPath SGPath::fromUtf8(const std::string& bytes, PermissionChecker p) return SGPath(bytes, p); } - -SGPath::SGPath(const SGPath& p) : - path(p.path), - _permission_checker(p._permission_checker), - _cached(p._cached), - _rwCached(p._rwCached), - _cacheEnabled(p._cacheEnabled), - _canRead(p._canRead), - _canWrite(p._canWrite), - _exists(p._exists), - _isDir(p._isDir), - _isFile(p._isFile), - _modTime(p._modTime), - _size(p._size) -{ -} - -SGPath& SGPath::operator=(const SGPath& p) -{ - path = p.path; - _permission_checker = p._permission_checker, - _cached = p._cached; - _rwCached = p._rwCached; - _cacheEnabled = p._cacheEnabled; - _canRead = p._canRead; - _canWrite = p._canWrite; - _exists = p._exists; - _isDir = p._isDir; - _isFile = p._isFile; - _modTime = p._modTime; - _size = p._size; - return *this; -} - -// destructor -SGPath::~SGPath() { -} - // set path void SGPath::set( const string& p ) { path = p; diff --git a/simgear/misc/sg_path.hxx b/simgear/misc/sg_path.hxx index 38b391a6..75129164 100644 --- a/simgear/misc/sg_path.hxx +++ b/simgear/misc/sg_path.hxx @@ -65,11 +65,6 @@ public: /** Default constructor */ explicit SGPath(PermissionChecker validator = NULL); - /** Copy contructor */ - SGPath(const SGPath& p); - - SGPath& operator=(const SGPath& p); - /** * Construct a path based on the starting path provided. * @param p initial path @@ -87,9 +82,6 @@ public: const std::string& r, PermissionChecker validator = NULL ); - /** Destructor */ - ~SGPath(); - /** * Set path to a new value * @param p new path From 1540d6f4727af985c5213b5768e1d10a05a80b8f Mon Sep 17 00:00:00 2001 From: Florent Rougon Date: Sat, 18 Nov 2017 15:51:13 +0100 Subject: [PATCH 03/18] SGPath: mark the str() and utf8Str() methods as 'noexcept' We'll use this to cleanly declare std::hash as 'noexcept' in the next commit, which appears to be desirable for std::hash template specializations, according to: http://en.cppreference.com/w/cpp/utility/hash --- simgear/misc/sg_path.hxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simgear/misc/sg_path.hxx b/simgear/misc/sg_path.hxx index 75129164..f18ffe18 100644 --- a/simgear/misc/sg_path.hxx +++ b/simgear/misc/sg_path.hxx @@ -182,8 +182,8 @@ public: * Get the path string * @return path string */ - std::string str() const { return path; } - std::string utf8Str() const { return path; } + std::string str() const noexcept { return path; } + std::string utf8Str() const noexcept { return path; } std::string local8BitStr() const; From 6064be33e5bd76460982b252b6c04c1a353a6a85 Mon Sep 17 00:00:00 2001 From: Florent Rougon Date: Sat, 18 Nov 2017 14:25:01 +0100 Subject: [PATCH 04/18] SGPath: add comparison operators (<, >, <=, >=) and an std::hash specialization This allows one to use SGPath in containers such as std::map, std::unordered_map and std::unordered_set. Like the existing == and !=, all these operators rely solely on the UTF-8 internal representation of the path. --- simgear/misc/path_test.cxx | 56 ++++++++++++++++++++++++++++++++++---- simgear/misc/sg_path.cxx | 12 ++++++++ simgear/misc/sg_path.hxx | 28 +++++++++++++++++-- 3 files changed, 88 insertions(+), 8 deletions(-) diff --git a/simgear/misc/path_test.cxx b/simgear/misc/path_test.cxx index d9364336..19e82a27 100644 --- a/simgear/misc/path_test.cxx +++ b/simgear/misc/path_test.cxx @@ -2,7 +2,11 @@ #include +#include +#include #include +#include + #include #include @@ -286,6 +290,49 @@ void test_permissions() SG_CHECK_EQUAL(fileInRW.canWrite(), false); } +void test_comparisons() +{ + std::cout << "Testing comparisons\n"; + + SG_CHECK_EQUAL(SGPath("/abc/def ghi"), SGPath("/abc/def ghi")); + SG_CHECK_NE(SGPath("/abc"), SGPath("abc")); + SG_CHECK_LT(SGPath(""), SGPath("/")); + SG_CHECK_LT(SGPath("A"), SGPath("a")); + SG_CHECK_LE(SGPath(""), SGPath("/")); + SG_CHECK_LE(SGPath("/"), SGPath("/")); + SG_CHECK_GT(SGPath("a"), SGPath("A")); + SG_CHECK_GE(SGPath("a"), SGPath("A")); + SG_CHECK_GE(SGPath("a"), SGPath("a")); + + std::vector origVector({ + std::string("/zer/gh/tr aze"), + std::string("/abc/def/ttt"), + std::string("/abc/def/ddd"), + std::string("/a"), + std::string("")}); + std::vector sortedVector({ + std::string(""), + std::string("/a"), + std::string("/abc/def/ddd"), + std::string("/abc/def/ttt"), + std::string("/zer/gh/tr aze")}); + + std::sort(origVector.begin(), origVector.end()); + SG_CHECK_EQUAL_NOSTREAM(origVector, sortedVector); +} + +void test_hash_function() +{ + std::cout << "Testing the std::hash specialization\n"; + + const SGPath nullPath{}; + const SGPath p{"/abc/def"}; + + SG_CHECK_EQUAL(std::hash{}(nullPath), std::hash{}(nullPath)); + SG_CHECK_EQUAL(std::hash{}(p), std::hash{}(p)); + SG_CHECK_NE(std::hash{}(p), std::hash{}(p / "foobar")); +} + int main(int argc, char* argv[]) { SGPath pa; @@ -389,12 +436,11 @@ int main(int argc, char* argv[]) SG_CHECK_EQUAL(pp.canWrite(), false); test_dir(); - - test_path_dir(); - + test_path_dir(); test_permissions(); - - test_update_dir(); + test_update_dir(); + test_comparisons(); + test_hash_function(); cout << "all tests passed OK" << endl; return 0; // passed diff --git a/simgear/misc/sg_path.cxx b/simgear/misc/sg_path.cxx index 31f84bc7..299a004c 100644 --- a/simgear/misc/sg_path.cxx +++ b/simgear/misc/sg_path.cxx @@ -742,6 +742,18 @@ bool SGPath::operator!=(const SGPath& other) const return (path != other.path); } +bool operator<(const SGPath& lhs, const SGPath& rhs) +{ return lhs.path < rhs.path; } + +bool operator>(const SGPath& lhs, const SGPath& rhs) +{ return operator<(rhs, lhs); } + +bool operator<=(const SGPath& lhs, const SGPath& rhs) +{ return !operator>(lhs, rhs); } + +bool operator>=(const SGPath& lhs, const SGPath& rhs) +{ return !operator<(lhs, rhs); } + //------------------------------------------------------------------------------ bool SGPath::rename(const SGPath& newName) { diff --git a/simgear/misc/sg_path.hxx b/simgear/misc/sg_path.hxx index f18ffe18..a9ef7c03 100644 --- a/simgear/misc/sg_path.hxx +++ b/simgear/misc/sg_path.hxx @@ -28,12 +28,14 @@ #ifndef _SG_PATH_HXX #define _SG_PATH_HXX +#include +#include + +#include +#include #include #include -#include -#include - #include #ifdef _MSC_VER @@ -91,6 +93,8 @@ public: bool operator==(const SGPath& other) const; bool operator!=(const SGPath& other) const; + // Other comparison operators are declared below + friend bool operator<(const SGPath& lhs, const SGPath& rhs); void setPermissionChecker(PermissionChecker validator); PermissionChecker getPermissionChecker() const; @@ -349,6 +353,24 @@ private: mutable size_t _size; }; +// Other comparison operators are in the class definition block +bool operator> (const SGPath& lhs, const SGPath& rhs); +bool operator<=(const SGPath& lhs, const SGPath& rhs); +bool operator>=(const SGPath& lhs, const SGPath& rhs); + +// Hash function for SGPath +namespace std +{ +template<> +struct hash +{ + std::size_t operator()(const SGPath& path) const noexcept + { + return std::hash{}(path.utf8Str()); + } +}; +} // of namespace std + /// Output to an ostream template inline From bd3c351f1f3cadb68ef4028d386739ac93a25fa6 Mon Sep 17 00:00:00 2001 From: Florent Rougon Date: Sat, 18 Nov 2017 22:27:47 +0100 Subject: [PATCH 05/18] Add function template simgear::enumValue() to simgear/sg_inlines.h This function template is useful to get the value of a member of a scoped enumeration, without having to hardcode its type while casting it. --- simgear/sg_inlines.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/simgear/sg_inlines.h b/simgear/sg_inlines.h index b21304d8..4c4b4ad5 100644 --- a/simgear/sg_inlines.h +++ b/simgear/sg_inlines.h @@ -23,6 +23,7 @@ // // $Id$ +#include #include #ifndef _SG_INLINES_H @@ -123,6 +124,17 @@ void noexceptSwap(T& a, T& b) noexcept swap(a, b); } +// Cast an enum value to its underlying type (useful with scoped enumerations). +// +// Example: enum class MyEnum { first = 1, second }; +// auto e = MyEnum::second; +// std::string msg = "MyEnum::second is " + +// std::to_string(simgear::enumValue(e)); +template +constexpr typename std::underlying_type::type enumValue(T e) { + return static_cast::type>(e); +} + } // of namespace simgear #endif // _SG_INLINES_H From e12fc5a89d1b0171b0668ce2af595be7c726aa80 Mon Sep 17 00:00:00 2001 From: Florent Rougon Date: Sun, 19 Nov 2017 08:15:44 +0100 Subject: [PATCH 06/18] Use common definition of simgear::enumValue() from This avoids code duplication. --- simgear/io/iostreams/zlibstream.cxx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/simgear/io/iostreams/zlibstream.cxx b/simgear/io/iostreams/zlibstream.cxx index 428cb538..2a4c36e1 100644 --- a/simgear/io/iostreams/zlibstream.cxx +++ b/simgear/io/iostreams/zlibstream.cxx @@ -38,20 +38,17 @@ #include +#include #include #include #include +#include #include -#include using std::string; -using traits = std::char_traits; +using simgear::enumValue; -// Cast an enum value to its underlying type -template -static constexpr typename std::underlying_type::type enumValue(T e) { - return static_cast::type>(e); -} +using traits = std::char_traits; // Private utility function static string zlibErrorMessage(const z_stream& zstream, int errorCode) From b766ce76ffe15fd5b39504f9ee77417dd1050b93 Mon Sep 17 00:00:00 2001 From: James Turner Date: Mon, 27 Nov 2017 23:37:56 +0000 Subject: [PATCH 07/18] Package thumbnail caching tweaks Resolves some issue with expired thumbnails not being reloaded correctly. --- simgear/package/Root.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/simgear/package/Root.cxx b/simgear/package/Root.cxx index ca567218..ec167000 100644 --- a/simgear/package/Root.cxx +++ b/simgear/package/Root.cxx @@ -151,13 +151,14 @@ public: std::string u = dl->realUrl(); if (status == Delegate::STATUS_SUCCESS) { thumbnailCache[u].requestPending = false; - fireDataForThumbnail(u, reinterpret_cast(bytes.data()), bytes.size()); // if this was a network load, rather than a re-load from the disk cache, // then persist to disk now. if (strutils::starts_with(request->url(), "http")) { addToPersistentCache(u, bytes); } + + fireDataForThumbnail(u, reinterpret_cast(bytes.data()), bytes.size()); } else if (status == Delegate::FAIL_HTTP_FORBIDDEN) { // treat this as rate-limiting failure, at least from some mirrors // (eg Ibiblio) and retry up to the max count @@ -220,6 +221,10 @@ public: sg_ofstream fstream(cachePath, std::ios::out | std::ios::trunc | std::ios::binary); fstream.write(imageBytes.data(), imageBytes.size()); fstream.close(); + + auto it = thumbnailCache.find(url); + assert(it != thumbnailCache.end()); + it->second.pathOnDisk = cachePath; } bool checkPersistentCache(const std::string& url) From 4f63c3f8a868d54ce4f8cd682591b4c68013b7a8 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Wed, 15 Nov 2017 19:31:29 +0100 Subject: [PATCH 08/18] nasal::Object: Simplify with C++11 C++11 variadic templates finally allow us to get rid of the ugly boost preprocessor workaround. --- simgear/nasal/cppbind/CMakeLists.txt | 1 - simgear/nasal/cppbind/NasalObject.hxx | 24 +++++++------ .../NasalObject_callMethod_templates.hxx | 35 ------------------- 3 files changed, 14 insertions(+), 46 deletions(-) delete mode 100644 simgear/nasal/cppbind/detail/NasalObject_callMethod_templates.hxx diff --git a/simgear/nasal/cppbind/CMakeLists.txt b/simgear/nasal/cppbind/CMakeLists.txt index 9d005394..5ef4a5aa 100644 --- a/simgear/nasal/cppbind/CMakeLists.txt +++ b/simgear/nasal/cppbind/CMakeLists.txt @@ -17,7 +17,6 @@ set(DETAIL_HEADERS detail/from_nasal_helper.hxx detail/functor_templates.hxx detail/nasal_traits.hxx - detail/NasalObject_callMethod_templates.hxx detail/to_nasal_helper.hxx ) diff --git a/simgear/nasal/cppbind/NasalObject.hxx b/simgear/nasal/cppbind/NasalObject.hxx index 05543254..565c1670 100644 --- a/simgear/nasal/cppbind/NasalObject.hxx +++ b/simgear/nasal/cppbind/NasalObject.hxx @@ -23,9 +23,6 @@ #include "NasalObjectHolder.hxx" #include "Ghost.hxx" -#include -#include - namespace nasal { /** @@ -48,14 +45,21 @@ namespace nasal bool valid() const; - // Build dependency for CMake, gcc, etc. -#define SG_DONT_DO_ANYTHING -# include -#undef SG_DONT_DO_ANYTHING + template + Ret callMethod(const std::string& name, Args ... args) + { + if( !_nasal_impl.valid() ) + return Ret(); -#define BOOST_PP_ITERATION_LIMITS (0, 9) -#define BOOST_PP_FILENAME_1 -#include BOOST_PP_ITERATE() + Context ctx; + auto func = get_member>( + ctx, _nasal_impl.get_naRef(), name + ); + if( func ) + return func(nasal::to_nasal(ctx, this), args...); + + return Ret(); + } bool _set(naContext c, const std::string& key, naRef val); bool _get(naContext c, const std::string& key, naRef& out); diff --git a/simgear/nasal/cppbind/detail/NasalObject_callMethod_templates.hxx b/simgear/nasal/cppbind/detail/NasalObject_callMethod_templates.hxx deleted file mode 100644 index 41dd9fd4..00000000 --- a/simgear/nasal/cppbind/detail/NasalObject_callMethod_templates.hxx +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef SG_NASAL_OBJECT_HXX_ -# error Nasal cppbind - do not include this file! -#endif - -#ifndef SG_DONT_DO_ANYTHING -#define n BOOST_PP_ITERATION() - -#define SG_CALL_ARG(z, n, dummy)\ - to_nasal::param_type>(ctx, a##n) - - template< - class Ret - BOOST_PP_ENUM_TRAILING_PARAMS(n, class A) - > - Ret callMethod( const std::string& name - BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(n, A, a) ) - { - if( !_nasal_impl.valid() ) - return Ret(); - - typedef boost::function - MemFunc; - - Context ctx; - MemFunc f = get_member(ctx, _nasal_impl.get_naRef(), name.c_str()); - if( f ) - return f(nasal::to_nasal(ctx, this) BOOST_PP_ENUM_TRAILING_PARAMS(n, a)); - - return Ret(); - } - -#undef SG_CALL_ARG - -#undef n -#endif // SG_DONT_DO_ANYTHING From 15d5c878f38803d1db7a172255a8f4286079fcea Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Fri, 1 Dec 2017 08:14:44 +0100 Subject: [PATCH 09/18] canvas::NasalWidget: don't call unsafe method in destructor Calling a virtual method in a destructor has undefined behaviour. Furthermore passing 'this' to nasal from within the destructor is not safe. 'onRemove' is called for widgets within layouts on destruction anyhow, so no need to call it here again. If widgets are arranged manually without any layout 'onRemoved' should be called upon removing them from a dialog. --- simgear/canvas/layout/NasalWidget.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/canvas/layout/NasalWidget.cxx b/simgear/canvas/layout/NasalWidget.cxx index 79b1be70..65ded50b 100644 --- a/simgear/canvas/layout/NasalWidget.cxx +++ b/simgear/canvas/layout/NasalWidget.cxx @@ -45,7 +45,7 @@ namespace canvas //---------------------------------------------------------------------------- NasalWidget::~NasalWidget() { - onRemove(); + } //---------------------------------------------------------------------------- From fe0d3fd448ec105a35a8364c1313082d91f25cc1 Mon Sep 17 00:00:00 2001 From: Alessandro Menti Date: Sat, 2 Dec 2017 15:31:58 +0100 Subject: [PATCH 10/18] Remove the dependency on the UTF-8 external library Remove the dependency on the UTF-8 external library by writing the UTF-8/code point conversion routines in KeyboardEvent.cxx. --- 3rdparty/CMakeLists.txt | 2 - 3rdparty/utf8/CMakeLists.txt | 17 - 3rdparty/utf8/doc/ReleaseNotes | 12 - 3rdparty/utf8/doc/utf8cpp.html | 1789 ----------------------- 3rdparty/utf8/source/utf8.h | 34 - 3rdparty/utf8/source/utf8/checked.h | 327 ----- 3rdparty/utf8/source/utf8/core.h | 329 ----- 3rdparty/utf8/source/utf8/unchecked.h | 228 --- simgear/canvas/events/KeyboardEvent.cxx | 45 +- 9 files changed, 39 insertions(+), 2744 deletions(-) delete mode 100644 3rdparty/utf8/CMakeLists.txt delete mode 100644 3rdparty/utf8/doc/ReleaseNotes delete mode 100644 3rdparty/utf8/doc/utf8cpp.html delete mode 100644 3rdparty/utf8/source/utf8.h delete mode 100644 3rdparty/utf8/source/utf8/checked.h delete mode 100644 3rdparty/utf8/source/utf8/core.h delete mode 100644 3rdparty/utf8/source/utf8/unchecked.h diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index a03a82d0..66a0777c 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -2,8 +2,6 @@ if (NOT SYSTEM_EXPAT) add_subdirectory(expat) endif() -add_subdirectory(utf8) - if (ENABLE_DNS AND NOT SYSTEM_UDNS) add_subdirectory(udns) endif() diff --git a/3rdparty/utf8/CMakeLists.txt b/3rdparty/utf8/CMakeLists.txt deleted file mode 100644 index 9aeed1c3..00000000 --- a/3rdparty/utf8/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -include (SimGearComponent) - -set(HEADERS - source/utf8.h -) - -set(HEADERS_utf8 - source/utf8/checked.h - source/utf8/core.h - source/utf8/unchecked.h -) - -set(SOURCES -) - -simgear_component(utf8 3rdparty/utf8 "${SOURCES}" "${HEADERS}") -simgear_component(utf8-internal 3rdparty/utf8/utf8 "" "${HEADERS_utf8}") \ No newline at end of file diff --git a/3rdparty/utf8/doc/ReleaseNotes b/3rdparty/utf8/doc/ReleaseNotes deleted file mode 100644 index 364411a2..00000000 --- a/3rdparty/utf8/doc/ReleaseNotes +++ /dev/null @@ -1,12 +0,0 @@ -utf8 cpp library -Release 2.3.4 - -A minor bug fix release. Thanks to all who reported bugs. - -Note: Version 2.3.3 contained a regression, and therefore was removed. - -Changes from version 2.3.2 -- Bug fix [39]: checked.h Line 273 and unchecked.h Line 182 have an extra ';' -- Bug fix [36]: replace_invalid() only works with back_inserter - -Files included in the release: utf8.h, core.h, checked.h, unchecked.h, utf8cpp.html, ReleaseNotes diff --git a/3rdparty/utf8/doc/utf8cpp.html b/3rdparty/utf8/doc/utf8cpp.html deleted file mode 100644 index 6f2aacbe..00000000 --- a/3rdparty/utf8/doc/utf8cpp.html +++ /dev/null @@ -1,1789 +0,0 @@ - - - - - - - - - UTF8-CPP: UTF-8 with C++ in a Portable Way - - - - -

- UTF8-CPP: UTF-8 with C++ in a Portable Way -

-

- The Sourceforge project page -

- -

- Introduction -

-

- Many C++ developers miss an easy and portable way of handling Unicode encoded - strings. The original C++ Standard (known as C++98 or C++03) is Unicode agnostic. - C++11 provides some support for Unicode on core language and library level: - u8, u, and U character and string literals, char16_t and char32_t character types, - u16string and u32string library classes, and codecvt support for conversions - between Unicode encoding forms. - In the meantime, developers use third party libraries like ICU, OS specific capabilities, or simply - roll out their own solutions. -

-

- In order to easily handle UTF-8 encoded Unicode strings, I came up with a small - generic library. For anybody used to work with STL algorithms and iterators, it should be - easy and natural to use. The code is freely available for any purpose - check out - the license at the beginning of the utf8.h file. If you run into - bugs or performance issues, please let me know and I'll do my best to address them. -

-

- The purpose of this article is not to offer an introduction to Unicode in general, - and UTF-8 in particular. If you are not familiar with Unicode, be sure to check out - Unicode Home Page or some other source of - information for Unicode. Also, it is not my aim to advocate the use of UTF-8 - encoded strings in C++ programs; if you want to handle UTF-8 encoded strings from - C++, I am sure you have good reasons for it. -

-

- Examples of use -

-

- Introductionary Sample -

-

- To illustrate the use of the library, let's start with a small but complete program - that opens a file containing UTF-8 encoded text, reads it line by line, checks each line - for invalid UTF-8 byte sequences, and converts it to UTF-16 encoding and back to UTF-8: -

-
-#include <fstream>
-#include <iostream>
-#include <string>
-#include <vector>
-#include "utf8.h"
-using namespace std;
-int main(int argc, char** argv)
-{
-    if (argc != 2) {
-        cout << "\nUsage: docsample filename\n";
-        return 0;
-    }
-
-    const char* test_file_path = argv[1];
-    // Open the test file (contains UTF-8 encoded text)
-    ifstream fs8(test_file_path);
-    if (!fs8.is_open()) {
-    cout << "Could not open " << test_file_path << endl;
-    return 0;
-    }
-
-    unsigned line_count = 1;
-    string line;
-    // Play with all the lines in the file
-    while (getline(fs8, line)) {
-       // check for invalid utf-8 (for a simple yes/no check, there is also utf8::is_valid function)
-        string::iterator end_it = utf8::find_invalid(line.begin(), line.end());
-        if (end_it != line.end()) {
-            cout << "Invalid UTF-8 encoding detected at line " << line_count << "\n";
-            cout << "This part is fine: " << string(line.begin(), end_it) << "\n";
-        }
-
-        // Get the line length (at least for the valid part)
-        int length = utf8::distance(line.begin(), end_it);
-        cout << "Length of line " << line_count << " is " << length <<  "\n";
-
-        // Convert it to utf-16
-        vector<unsigned short> utf16line;
-        utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
-
-        // And back to utf-8
-        string utf8line; 
-        utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8line));
-
-        // Confirm that the conversion went OK:
-        if (utf8line != string(line.begin(), end_it))
-            cout << "Error in UTF-16 conversion at line: " << line_count << "\n";        
-
-        line_count++;
-    }
-    return 0;
-}
-
-

- In the previous code sample, for each line we performed - a detection of invalid UTF-8 sequences with find_invalid; the number - of characters (more precisely - the number of Unicode code points, including the end - of line and even BOM if there is one) in each line was - determined with a use of utf8::distance; finally, we have converted - each line to UTF-16 encoding with utf8to16 and back to UTF-8 with - utf16to8. -

-

Checking if a file contains valid UTF-8 text

-

-Here is a function that checks whether the content of a file is valid UTF-8 encoded text without -reading the content into the memory: -

-
    
-bool valid_utf8_file(iconst char* file_name)
-{
-    ifstream ifs(file_name);
-    if (!ifs)
-        return false; // even better, throw here
-
-    istreambuf_iterator<char> it(ifs.rdbuf());
-    istreambuf_iterator<char> eos;
-
-    return utf8::is_valid(it, eos);
-}
-
-

-Because the function utf8::is_valid() works with input iterators, we were able -to pass an istreambuf_iterator to it and read the content of the file directly -without loading it to the memory first.

-

-Note that other functions that take input iterator arguments can be used in a similar way. For -instance, to read the content of a UTF-8 encoded text file and convert the text to UTF-16, just -do something like: -

-
-    utf8::utf8to16(it, eos, back_inserter(u16string));
-
-

Ensure that a string contains valid UTF-8 text

-

-If we have some text that "probably" contains UTF-8 encoded text and we want to -replace any invalid UTF-8 sequence with a replacement character, something like -the following function may be used: -

-
-void fix_utf8_string(std::string& str)
-{
-    std::string temp;
-    utf8::replace_invalid(str.begin(), str.end(), back_inserter(temp));
-    str = temp;
-}
-
-

The function will replace any invalid UTF-8 sequence with a Unicode replacement character. -There is an overloaded function that enables the caller to supply their own replacement character. -

-

- Reference -

-

- Functions From utf8 Namespace -

-

- utf8::append -

-

- Available in version 1.0 and later. -

-

- Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence - to a UTF-8 string. -

-
-template <typename octet_iterator>
-octet_iterator append(uint32_t cp, octet_iterator result);
-   
-
-

- octet_iterator: an output iterator.
- cp: a 32 bit integer representing a code point to append to the - sequence.
- result: an output iterator to the place in the sequence where to - append the code point.
- Return value: an iterator pointing to the place - after the newly appended sequence. -

-

- Example of use: -

-
-unsigned char u[5] = {0,0,0,0,0};
-unsigned char* end = append(0x0448, u);
-assert (u[0] == 0xd1 && u[1] == 0x88 && u[2] == 0 && u[3] == 0 && u[4] == 0);
-
-

- Note that append does not allocate any memory - it is the burden of - the caller to make sure there is enough memory allocated for the operation. To make - things more interesting, append can add anywhere between 1 and 4 - octets to the sequence. In practice, you would most often want to use - std::back_inserter to ensure that the necessary memory is allocated. -

-

- In case of an invalid code point, a utf8::invalid_code_point exception - is thrown. -

-

- utf8::next -

-

- Available in version 1.0 and later. -

-

- Given the iterator to the beginning of the UTF-8 sequence, it returns the code - point and moves the iterator to the next position. -

-
-template <typename octet_iterator> 
-uint32_t next(octet_iterator& it, octet_iterator end);
-   
-
-

- octet_iterator: an input iterator.
- it: a reference to an iterator pointing to the beginning of an UTF-8 - encoded code point. After the function returns, it is incremented to point to the - beginning of the next code point.
- end: end of the UTF-8 sequence to be processed. If it - gets equal to end during the extraction of a code point, an - utf8::not_enough_room exception is thrown.
- Return value: the 32 bit representation of the - processed UTF-8 code point. -

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-char* w = twochars;
-int cp = next(w, twochars + 6);
-assert (cp == 0x65e5);
-assert (w == twochars + 3);
-
-

- This function is typically used to iterate through a UTF-8 encoded string. -

-

- In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is - thrown. -

-

- utf8::peek_next -

-

- Available in version 2.1 and later. -

-

- Given the iterator to the beginning of the UTF-8 sequence, it returns the code - point for the following sequence without changing the value of the iterator. -

-
-template <typename octet_iterator> 
-uint32_t peek_next(octet_iterator it, octet_iterator end);
-   
-
-

- octet_iterator: an input iterator.
- it: an iterator pointing to the beginning of an UTF-8 - encoded code point.
- end: end of the UTF-8 sequence to be processed. If it - gets equal to end during the extraction of a code point, an - utf8::not_enough_room exception is thrown.
- Return value: the 32 bit representation of the - processed UTF-8 code point. -

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-char* w = twochars;
-int cp = peek_next(w, twochars + 6);
-assert (cp == 0x65e5);
-assert (w == twochars);
-
-

- In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is - thrown. -

-

- utf8::prior -

-

- Available in version 1.02 and later. -

-

- Given a reference to an iterator pointing to an octet in a UTF-8 sequence, it - decreases the iterator until it hits the beginning of the previous UTF-8 encoded - code point and returns the 32 bits representation of the code point. -

-
-template <typename octet_iterator> 
-uint32_t prior(octet_iterator& it, octet_iterator start);
-   
-
-

- octet_iterator: a bidirectional iterator.
- it: a reference pointing to an octet within a UTF-8 encoded string. - After the function returns, it is decremented to point to the beginning of the - previous code point.
- start: an iterator to the beginning of the sequence where the search - for the beginning of a code point is performed. It is a - safety measure to prevent passing the beginning of the string in the search for a - UTF-8 lead octet.
- Return value: the 32 bit representation of the - previous code point. -

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-unsigned char* w = twochars + 3;
-int cp = prior (w, twochars);
-assert (cp == 0x65e5);
-assert (w == twochars);
-
-

- This function has two purposes: one is two iterate backwards through a UTF-8 - encoded string. Note that it is usually a better idea to iterate forward instead, - since utf8::next is faster. The second purpose is to find a beginning - of a UTF-8 sequence if we have a random position within a string. Note that in that - case utf8::prior may not detect an invalid UTF-8 sequence in some scenarios: - for instance if there are superfluous trail octets, it will just skip them. -

-

- it will typically point to the beginning of - a code point, and start will point to the - beginning of the string to ensure we don't go backwards too far. it is - decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence - beginning with that octet is decoded to a 32 bit representation and returned. -

-

- In case start is reached before a UTF-8 lead octet is hit, or if an - invalid UTF-8 sequence is started by the lead octet, an invalid_utf8 - exception is thrown. -

-

In case start equals it, a not_enough_room - exception is thrown. -

- utf8::previous -

-

- Deprecated in version 1.02 and later. -

-

- Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it - decreases the iterator until it hits the beginning of the previous UTF-8 encoded - code point and returns the 32 bits representation of the code point. -

-
-template <typename octet_iterator> 
-uint32_t previous(octet_iterator& it, octet_iterator pass_start);
-   
-
-

- octet_iterator: a random access iterator.
- it: a reference pointing to an octet within a UTF-8 encoded string. - After the function returns, it is decremented to point to the beginning of the - previous code point.
- pass_start: an iterator to the point in the sequence where the search - for the beginning of a code point is aborted if no result was reached. It is a - safety measure to prevent passing the beginning of the string in the search for a - UTF-8 lead octet.
- Return value: the 32 bit representation of the - previous code point. -

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-unsigned char* w = twochars + 3;
-int cp = previous (w, twochars - 1);
-assert (cp == 0x65e5);
-assert (w == twochars);
-
-

- utf8::previous is deprecated, and utf8::prior should - be used instead, although the existing code can continue using this function. - The problem is the parameter pass_start that points to the position - just before the beginning of the sequence. Standard containers don't have the - concept of "pass start" and the function can not be used with their iterators. -

-

- it will typically point to the beginning of - a code point, and pass_start will point to the octet just before the - beginning of the string to ensure we don't go backwards too far. it is - decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence - beginning with that octet is decoded to a 32 bit representation and returned. -

-

- In case pass_start is reached before a UTF-8 lead octet is hit, or if an - invalid UTF-8 sequence is started by the lead octet, an invalid_utf8 - exception is thrown -

-

- utf8::advance -

-

- Available in version 1.0 and later. -

-

- Advances an iterator by the specified number of code points within an UTF-8 - sequence. -

-
-template <typename octet_iterator, typename distance_type> 
-void advance (octet_iterator& it, distance_type n, octet_iterator end);
-   
-
-

- octet_iterator: an input iterator.
- distance_type: an integral type convertible to octet_iterator's difference type.
- it: a reference to an iterator pointing to the beginning of an UTF-8 - encoded code point. After the function returns, it is incremented to point to the - nth following code point.
- n: a positive integer that shows how many code points we want to - advance.
- end: end of the UTF-8 sequence to be processed. If it - gets equal to end during the extraction of a code point, an - utf8::not_enough_room exception is thrown.
-

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-unsigned char* w = twochars;
-advance (w, 2, twochars + 6);
-assert (w == twochars + 5);
-
-

- This function works only "forward". In case of a negative n, there is - no effect. -

-

- In case of an invalid code point, a utf8::invalid_code_point exception - is thrown. -

-

- utf8::distance -

-

- Available in version 1.0 and later. -

-

- Given the iterators to two UTF-8 encoded code points in a seqence, returns the - number of code points between them. -

-
-template <typename octet_iterator> 
-typename std::iterator_traits<octet_iterator>::difference_type distance (octet_iterator first, octet_iterator last);
-   
-
-

- octet_iterator: an input iterator.
- first: an iterator to a beginning of a UTF-8 encoded code point.
- last: an iterator to a "post-end" of the last UTF-8 encoded code - point in the sequence we are trying to determine the length. It can be the - beginning of a new code point, or not.
- Return value the distance between the iterators, - in code points. -

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-size_t dist = utf8::distance(twochars, twochars + 5);
-assert (dist == 2);
-
-

- This function is used to find the length (in code points) of a UTF-8 encoded - string. The reason it is called distance, rather than, say, - length is mainly because developers are used that length is an - O(1) function. Computing the length of an UTF-8 string is a linear operation, and - it looked better to model it after std::distance algorithm. -

-

- In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is - thrown. If last does not point to the past-of-end of a UTF-8 seqence, - a utf8::not_enough_room exception is thrown. -

-

- utf8::utf16to8 -

-

- Available in version 1.0 and later. -

-

- Converts a UTF-16 encoded string to UTF-8. -

-
-template <typename u16bit_iterator, typename octet_iterator>
-octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
-   
-
-

- u16bit_iterator: an input iterator.
- octet_iterator: an output iterator.
- start: an iterator pointing to the beginning of the UTF-16 encoded - string to convert.
- end: an iterator pointing to pass-the-end of the UTF-16 encoded - string to convert.
- result: an output iterator to the place in the UTF-8 string where to - append the result of conversion.
- Return value: An iterator pointing to the place - after the appended UTF-8 string. -

-

- Example of use: -

-
-unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
-vector<unsigned char> utf8result;
-utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
-assert (utf8result.size() == 10);    
-
-

- In case of invalid UTF-16 sequence, a utf8::invalid_utf16 exception is - thrown. -

-

- utf8::utf8to16 -

-

- Available in version 1.0 and later. -

-

- Converts an UTF-8 encoded string to UTF-16 -

-
-template <typename u16bit_iterator, typename octet_iterator>
-u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
-   
-
-

- octet_iterator: an input iterator.
- u16bit_iterator: an output iterator.
- start: an iterator pointing to the beginning of the UTF-8 encoded - string to convert. < br /> end: an iterator pointing to - pass-the-end of the UTF-8 encoded string to convert.
- result: an output iterator to the place in the UTF-16 string where to - append the result of conversion.
- Return value: An iterator pointing to the place - after the appended UTF-16 string. -

-

- Example of use: -

-
-char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
-vector <unsigned short> utf16result;
-utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
-assert (utf16result.size() == 4);
-assert (utf16result[2] == 0xd834);
-assert (utf16result[3] == 0xdd1e);
-
-

- In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is - thrown. If end does not point to the past-of-end of a UTF-8 seqence, a - utf8::not_enough_room exception is thrown. -

-

- utf8::utf32to8 -

-

- Available in version 1.0 and later. -

-

- Converts a UTF-32 encoded string to UTF-8. -

-
-template <typename octet_iterator, typename u32bit_iterator>
-octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
-   
-
-

- octet_iterator: an output iterator.
- u32bit_iterator: an input iterator.
- start: an iterator pointing to the beginning of the UTF-32 encoded - string to convert.
- end: an iterator pointing to pass-the-end of the UTF-32 encoded - string to convert.
- result: an output iterator to the place in the UTF-8 string where to - append the result of conversion.
- Return value: An iterator pointing to the place - after the appended UTF-8 string. -

-

- Example of use: -

-
-int utf32string[] = {0x448, 0x65E5, 0x10346, 0};
-vector<unsigned char> utf8result;
-utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
-assert (utf8result.size() == 9);
-
-

- In case of invalid UTF-32 string, a utf8::invalid_code_point exception - is thrown. -

-

- utf8::utf8to32 -

-

- Available in version 1.0 and later. -

-

- Converts a UTF-8 encoded string to UTF-32. -

-
-template <typename octet_iterator, typename u32bit_iterator>
-u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
-   
-
-

- octet_iterator: an input iterator.
- u32bit_iterator: an output iterator.
- start: an iterator pointing to the beginning of the UTF-8 encoded - string to convert.
- end: an iterator pointing to pass-the-end of the UTF-8 encoded string - to convert.
- result: an output iterator to the place in the UTF-32 string where to - append the result of conversion.
- Return value: An iterator pointing to the place - after the appended UTF-32 string. -

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-vector<int> utf32result;
-utf8to32(twochars, twochars + 5, back_inserter(utf32result));
-assert (utf32result.size() == 2);
-
-

- In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is - thrown. If end does not point to the past-of-end of a UTF-8 seqence, a - utf8::not_enough_room exception is thrown. -

-

- utf8::find_invalid -

-

- Available in version 1.0 and later. -

-

- Detects an invalid sequence within a UTF-8 string. -

-
-template <typename octet_iterator> 
-octet_iterator find_invalid(octet_iterator start, octet_iterator end);
-
-

- octet_iterator: an input iterator.
- start: an iterator pointing to the beginning of the UTF-8 string to - test for validity.
- end: an iterator pointing to pass-the-end of the UTF-8 string to test - for validity.
- Return value: an iterator pointing to the first - invalid octet in the UTF-8 string. In case none were found, equals - end. -

-

- Example of use: -

-
-char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
-char* invalid = find_invalid(utf_invalid, utf_invalid + 6);
-assert (invalid == utf_invalid + 5);
-
-

- This function is typically used to make sure a UTF-8 string is valid before - processing it with other functions. It is especially important to call it if before - doing any of the unchecked operations on it. -

-

- utf8::is_valid -

-

- Available in version 1.0 and later. -

-

- Checks whether a sequence of octets is a valid UTF-8 string. -

-
-template <typename octet_iterator> 
-bool is_valid(octet_iterator start, octet_iterator end);
-   
-
-

- octet_iterator: an input iterator.
- start: an iterator pointing to the beginning of the UTF-8 string to - test for validity.
- end: an iterator pointing to pass-the-end of the UTF-8 string to test - for validity.
- Return value: true if the sequence - is a valid UTF-8 string; false if not. -

- Example of use: -
-char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
-bool bvalid = is_valid(utf_invalid, utf_invalid + 6);
-assert (bvalid == false);
-
-

- is_valid is a shorthand for find_invalid(start, end) == - end;. You may want to use it to make sure that a byte seqence is a valid - UTF-8 string without the need to know where it fails if it is not valid. -

-

- utf8::replace_invalid -

-

- Available in version 2.0 and later. -

-

- Replaces all invalid UTF-8 sequences within a string with a replacement marker. -

-
-template <typename octet_iterator, typename output_iterator>
-output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement);
-template <typename octet_iterator, typename output_iterator>
-output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out);
-   
-
-

- octet_iterator: an input iterator.
- output_iterator: an output iterator.
- start: an iterator pointing to the beginning of the UTF-8 string to - look for invalid UTF-8 sequences.
- end: an iterator pointing to pass-the-end of the UTF-8 string to look - for invalid UTF-8 sequences.
- out: An output iterator to the range where the result of replacement - is stored.
- replacement: A Unicode code point for the replacement marker. The - version without this parameter assumes the value 0xfffd
- Return value: An iterator pointing to the place - after the UTF-8 string with replaced invalid sequences. -

-

- Example of use: -

-
-char invalid_sequence[] = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
-vector<char> replace_invalid_result;
-replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), back_inserter(replace_invalid_result), '?');
-bvalid = is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
-assert (bvalid);
-char* fixed_invalid_sequence = "a????z";
-assert (std::equal(replace_invalid_result.begin(), replace_invalid_result.end(), fixed_invalid_sequence));
-
-

- replace_invalid does not perform in-place replacement of invalid - sequences. Rather, it produces a copy of the original string with the invalid - sequences replaced with a replacement marker. Therefore, out must not - be in the [start, end] range. -

-

- If end does not point to the past-of-end of a UTF-8 sequence, a - utf8::not_enough_room exception is thrown. -

-

- utf8::starts_with_bom -

-

- Available in version 2.3 and later. Relaces deprecated is_bom() function. -

-

- Checks whether an octet sequence starts with a UTF-8 byte order mark (BOM) -

-
-template <typename octet_iterator> 
-bool starts_with_bom (octet_iterator it, octet_iterator end);
-
-

- octet_iterator: an input iterator.
- it: beginning of the octet sequence to check
- end: pass-end of the sequence to check
- Return value: true if the sequence - starts with a UTF-8 byte order mark; false if not. -

-

- Example of use: -

-
-unsigned char byte_order_mark[] = {0xef, 0xbb, 0xbf};
-bool bbom = starts_with_bom(byte_order_mark, byte_order_mark + sizeof(byte_order_mark));
-assert (bbom == true);
-
-

- The typical use of this function is to check the first three bytes of a file. If - they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8 - encoded text. -

-

- utf8::is_bom -

-

- Available in version 1.0 and later. Deprecated in version 2.3. starts_with_bom() should be used - instead. -

-

- Checks whether a sequence of three octets is a UTF-8 byte order mark (BOM) -

-
-template <typename octet_iterator> 
-bool is_bom (octet_iterator it);  // Deprecated
-
-

- octet_iterator: an input iterator.
- it: beginning of the 3-octet sequence to check
- Return value: true if the sequence - is UTF-8 byte order mark; false if not. -

-

- Example of use: -

-
-unsigned char byte_order_mark[] = {0xef, 0xbb, 0xbf};
-bool bbom = is_bom(byte_order_mark);
-assert (bbom == true);
-
-

- The typical use of this function is to check the first three bytes of a file. If - they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8 - encoded text. -

-

- If a sequence is - shorter than three bytes, an invalid iterator will be dereferenced. Therefore, this function is deprecated - in favor of starts_with_bom()that takes the end of sequence as an argument. -

-

- Types From utf8 Namespace -

-

utf8::exception -

-

- Available in version 2.3 and later. -

-

- Base class for the exceptions thrown by UTF CPP library functions. -

-
-class exception : public std::exception {};
-
-

- Example of use: -

-
-try {
-  code_that_uses_utf_cpp_library();
-}
-catch(const utf8::exception& utfcpp_ex) {
-  cerr << utfcpp_ex.what();
-}
-
- -

utf8::invalid_code_point -

-

- Available in version 1.0 and later. -

-

- Thrown by UTF8 CPP functions such as advance and next if an UTF-8 sequence represents and invalid code point. -

- -
-class invalid_code_point : public exception {
-public: 
-    uint32_t code_point() const;
-};
-
-
-

- Member function code_point() can be used to determine the invalid code point that - caused the exception to be thrown. -

-

utf8::invalid_utf8 -

-

- Available in version 1.0 and later. -

-

- Thrown by UTF8 CPP functions such as next and prior if an invalid UTF-8 sequence - is detected during decoding. -

- -
-class invalid_utf8 : public exception {
-public: 
-    uint8_t utf8_octet() const;
-};
-
- -

- Member function utf8_octet() can be used to determine the beginning of the byte - sequence that caused the exception to be thrown. -

- -

utf8::invalid_utf16 -

-

- Available in version 1.0 and later. -

-

- Thrown by UTF8 CPP function utf16to8 if an invalid UTF-16 sequence - is detected during decoding. -

- -
-class invalid_utf16 : public exception {
-public: 
-    uint16_t utf16_word() const;
-};
-
- -

- Member function utf16_word() can be used to determine the UTF-16 code unit - that caused the exception to be thrown. -

-

utf8::not_enough_room -

-

- Available in version 1.0 and later. -

-

- Thrown by UTF8 CPP functions such as next if the end of the decoded UTF-8 sequence - was reached before the code point was decoded. -

- -
-class not_enough_room : public exception {};
-
-

- utf8::iterator -

-

- Available in version 2.0 and later. -

-

- Adapts the underlying octet iterator to iterate over the sequence of code points, - rather than raw octets. -

-
-template <typename octet_iterator>
-class iterator;
-
- -
Member functions
-
-
iterator();
the deafult constructor; the underlying octet_iterator is - constructed with its default constructor. -
explicit iterator (const octet_iterator& octet_it, - const octet_iterator& range_start, - const octet_iterator& range_end);
a constructor - that initializes the underlying octet_iterator with octet_it - and sets the range in which the iterator is considered valid. -
octet_iterator base () const;
returns the - underlying octet_iterator. -
uint32_t operator * () const;
decodes the utf-8 sequence - the underlying octet_iterator is pointing to and returns the code point. -
bool operator == (const iterator& rhs) - const;
returns true - if the two underlaying iterators are equal. -
bool operator != (const iterator& rhs) - const;
returns true - if the two underlaying iterators are not equal. -
iterator& operator ++ ();
the prefix increment - moves - the iterator to the next UTF-8 encoded code point. -
iterator operator ++ (int);
- the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one. -
iterator& operator -- ();
the prefix decrement - moves - the iterator to the previous UTF-8 encoded code point. -
iterator operator -- (int);
- the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one. -
-

- Example of use: -

-
-char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
-utf8::iterator<char*> it(threechars, threechars, threechars + 9);
-utf8::iterator<char*> it2 = it;
-assert (it2 == it);
-assert (*it == 0x10346);
-assert (*(++it) == 0x65e5);
-assert ((*it++) == 0x65e5);
-assert (*it == 0x0448);
-assert (it != it2);
-utf8::iterator<char*> endit (threechars + 9, threechars, threechars + 9);  
-assert (++it == endit);
-assert (*(--it) == 0x0448);
-assert ((*it--) == 0x0448);
-assert (*it == 0x65e5);
-assert (--it == utf8::iterator<char*>(threechars, threechars, threechars + 9));
-assert (*it == 0x10346);
-
-

- The purpose of utf8::iterator adapter is to enable easy iteration as well as the use of STL - algorithms with UTF-8 encoded strings. Increment and decrement operators are implemented in terms of - utf8::next() and utf8::prior() functions. -

-

- Note that utf8::iterator adapter is a checked iterator. It operates on the range specified in - the constructor; any attempt to go out of that range will result in an exception. Even the comparison operators - require both iterator object to be constructed against the same range - otherwise an exception is thrown. Typically, - the range will be determined by sequence container functions begin and end, i.e.: -

-
-std::string s = "example";
-utf8::iterator i (s.begin(), s.begin(), s.end());
-
-

- Functions From utf8::unchecked Namespace -

-

- utf8::unchecked::append -

-

- Available in version 1.0 and later. -

-

- Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence - to a UTF-8 string. -

-
-template <typename octet_iterator>
-octet_iterator append(uint32_t cp, octet_iterator result);
-   
-
-

- cp: A 32 bit integer representing a code point to append to the - sequence.
- result: An output iterator to the place in the sequence where to - append the code point.
- Return value: An iterator pointing to the place - after the newly appended sequence. -

-

- Example of use: -

-
-unsigned char u[5] = {0,0,0,0,0};
-unsigned char* end = unchecked::append(0x0448, u);
-assert (u[0] == 0xd1 && u[1] == 0x88 && u[2] == 0 && u[3] == 0 && u[4] == 0);
-
-

- This is a faster but less safe version of utf8::append. It does not - check for validity of the supplied code point, and may produce an invalid UTF-8 - sequence. -

-

- utf8::unchecked::next -

-

- Available in version 1.0 and later. -

-

- Given the iterator to the beginning of a UTF-8 sequence, it returns the code point - and moves the iterator to the next position. -

-
-template <typename octet_iterator>
-uint32_t next(octet_iterator& it);
-   
-
-

- it: a reference to an iterator pointing to the beginning of an UTF-8 - encoded code point. After the function returns, it is incremented to point to the - beginning of the next code point.
- Return value: the 32 bit representation of the - processed UTF-8 code point. -

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-char* w = twochars;
-int cp = unchecked::next(w);
-assert (cp == 0x65e5);
-assert (w == twochars + 3);
-
-

- This is a faster but less safe version of utf8::next. It does not - check for validity of the supplied UTF-8 sequence. -

-

- utf8::unchecked::peek_next -

-

- Available in version 2.1 and later. -

-

- Given the iterator to the beginning of a UTF-8 sequence, it returns the code point. -

-
-template <typename octet_iterator>
-uint32_t peek_next(octet_iterator it);
-   
-
-

- it: an iterator pointing to the beginning of an UTF-8 - encoded code point.
- Return value: the 32 bit representation of the - processed UTF-8 code point. -

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-char* w = twochars;
-int cp = unchecked::peek_next(w);
-assert (cp == 0x65e5);
-assert (w == twochars);
-
-

- This is a faster but less safe version of utf8::peek_next. It does not - check for validity of the supplied UTF-8 sequence. -

-

- utf8::unchecked::prior -

-

- Available in version 1.02 and later. -

-

- Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it - decreases the iterator until it hits the beginning of the previous UTF-8 encoded - code point and returns the 32 bits representation of the code point. -

-
-template <typename octet_iterator>
-uint32_t prior(octet_iterator& it);
-   
-
-

- it: a reference pointing to an octet within a UTF-8 encoded string. - After the function returns, it is decremented to point to the beginning of the - previous code point.
- Return value: the 32 bit representation of the - previous code point. -

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-char* w = twochars + 3;
-int cp = unchecked::prior (w);
-assert (cp == 0x65e5);
-assert (w == twochars);
-
-

- This is a faster but less safe version of utf8::prior. It does not - check for validity of the supplied UTF-8 sequence and offers no boundary checking. -

-

- utf8::unchecked::previous (deprecated, see utf8::unchecked::prior) -

-

- Deprecated in version 1.02 and later. -

-

- Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it - decreases the iterator until it hits the beginning of the previous UTF-8 encoded - code point and returns the 32 bits representation of the code point. -

-
-template <typename octet_iterator>
-uint32_t previous(octet_iterator& it);
-   
-
-

- it: a reference pointing to an octet within a UTF-8 encoded string. - After the function returns, it is decremented to point to the beginning of the - previous code point.
- Return value: the 32 bit representation of the - previous code point. -

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-char* w = twochars + 3;
-int cp = unchecked::previous (w);
-assert (cp == 0x65e5);
-assert (w == twochars);
-
-

- The reason this function is deprecated is just the consistency with the "checked" - versions, where prior should be used instead of previous. - In fact, unchecked::previous behaves exactly the same as - unchecked::prior -

-

- This is a faster but less safe version of utf8::previous. It does not - check for validity of the supplied UTF-8 sequence and offers no boundary checking. -

-

- utf8::unchecked::advance -

-

- Available in version 1.0 and later. -

-

- Advances an iterator by the specified number of code points within an UTF-8 - sequence. -

-
-template <typename octet_iterator, typename distance_type>
-void advance (octet_iterator& it, distance_type n);
-   
-
-

- it: a reference to an iterator pointing to the beginning of an UTF-8 - encoded code point. After the function returns, it is incremented to point to the - nth following code point.
- n: a positive integer that shows how many code points we want to - advance.
-

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-char* w = twochars;
-unchecked::advance (w, 2);
-assert (w == twochars + 5);
-
-

- This function works only "forward". In case of a negative n, there is - no effect. -

-

- This is a faster but less safe version of utf8::advance. It does not - check for validity of the supplied UTF-8 sequence and offers no boundary checking. -

-

- utf8::unchecked::distance -

-

- Available in version 1.0 and later. -

-

- Given the iterators to two UTF-8 encoded code points in a seqence, returns the - number of code points between them. -

-
-template <typename octet_iterator>
-typename std::iterator_traits<octet_iterator>::difference_type distance (octet_iterator first, octet_iterator last);
-
-

- first: an iterator to a beginning of a UTF-8 encoded code point.
- last: an iterator to a "post-end" of the last UTF-8 encoded code - point in the sequence we are trying to determine the length. It can be the - beginning of a new code point, or not.
- Return value the distance between the iterators, - in code points. -

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-size_t dist = utf8::unchecked::distance(twochars, twochars + 5);
-assert (dist == 2);
-
-

- This is a faster but less safe version of utf8::distance. It does not - check for validity of the supplied UTF-8 sequence. -

-

- utf8::unchecked::utf16to8 -

-

- Available in version 1.0 and later. -

-

- Converts a UTF-16 encoded string to UTF-8. -

-
-template <typename u16bit_iterator, typename octet_iterator>
-octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
-   
-
-

- start: an iterator pointing to the beginning of the UTF-16 encoded - string to convert.
- end: an iterator pointing to pass-the-end of the UTF-16 encoded - string to convert.
- result: an output iterator to the place in the UTF-8 string where to - append the result of conversion.
- Return value: An iterator pointing to the place - after the appended UTF-8 string. -

-

- Example of use: -

-
-unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
-vector<unsigned char> utf8result;
-unchecked::utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
-assert (utf8result.size() == 10);    
-
-

- This is a faster but less safe version of utf8::utf16to8. It does not - check for validity of the supplied UTF-16 sequence. -

-

- utf8::unchecked::utf8to16 -

-

- Available in version 1.0 and later. -

-

- Converts an UTF-8 encoded string to UTF-16 -

-
-template <typename u16bit_iterator, typename octet_iterator>
-u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
-   
-
-

- start: an iterator pointing to the beginning of the UTF-8 encoded - string to convert. < br /> end: an iterator pointing to - pass-the-end of the UTF-8 encoded string to convert.
- result: an output iterator to the place in the UTF-16 string where to - append the result of conversion.
- Return value: An iterator pointing to the place - after the appended UTF-16 string. -

-

- Example of use: -

-
-char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
-vector <unsigned short> utf16result;
-unchecked::utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
-assert (utf16result.size() == 4);
-assert (utf16result[2] == 0xd834);
-assert (utf16result[3] == 0xdd1e);
-
-

- This is a faster but less safe version of utf8::utf8to16. It does not - check for validity of the supplied UTF-8 sequence. -

-

- utf8::unchecked::utf32to8 -

-

- Available in version 1.0 and later. -

-

- Converts a UTF-32 encoded string to UTF-8. -

-
-template <typename octet_iterator, typename u32bit_iterator>
-octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
-   
-
-

- start: an iterator pointing to the beginning of the UTF-32 encoded - string to convert.
- end: an iterator pointing to pass-the-end of the UTF-32 encoded - string to convert.
- result: an output iterator to the place in the UTF-8 string where to - append the result of conversion.
- Return value: An iterator pointing to the place - after the appended UTF-8 string. -

-

- Example of use: -

-
-int utf32string[] = {0x448, 0x65e5, 0x10346, 0};
-vector<unsigned char> utf8result;
-utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
-assert (utf8result.size() == 9);
-
-

- This is a faster but less safe version of utf8::utf32to8. It does not - check for validity of the supplied UTF-32 sequence. -

-

- utf8::unchecked::utf8to32 -

-

- Available in version 1.0 and later. -

-

- Converts a UTF-8 encoded string to UTF-32. -

-
-template <typename octet_iterator, typename u32bit_iterator>
-u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
-   
-
-

- start: an iterator pointing to the beginning of the UTF-8 encoded - string to convert.
- end: an iterator pointing to pass-the-end of the UTF-8 encoded string - to convert.
- result: an output iterator to the place in the UTF-32 string where to - append the result of conversion.
- Return value: An iterator pointing to the place - after the appended UTF-32 string. -

-

- Example of use: -

-
-char* twochars = "\xe6\x97\xa5\xd1\x88";
-vector<int> utf32result;
-unchecked::utf8to32(twochars, twochars + 5, back_inserter(utf32result));
-assert (utf32result.size() == 2);
-
-

- This is a faster but less safe version of utf8::utf8to32. It does not - check for validity of the supplied UTF-8 sequence. -

-

- Types From utf8::unchecked Namespace -

-

- utf8::iterator -

-

- Available in version 2.0 and later. -

-

- Adapts the underlying octet iterator to iterate over the sequence of code points, - rather than raw octets. -

-
-template <typename octet_iterator>
-class iterator;
-
- -
Member functions
-
-
iterator();
the deafult constructor; the underlying octet_iterator is - constructed with its default constructor. -
explicit iterator (const octet_iterator& octet_it); -
a constructor - that initializes the underlying octet_iterator with octet_it -
octet_iterator base () const;
returns the - underlying octet_iterator. -
uint32_t operator * () const;
decodes the utf-8 sequence - the underlying octet_iterator is pointing to and returns the code point. -
bool operator == (const iterator& rhs) - const;
returns true - if the two underlaying iterators are equal. -
bool operator != (const iterator& rhs) - const;
returns true - if the two underlaying iterators are not equal. -
iterator& operator ++ ();
the prefix increment - moves - the iterator to the next UTF-8 encoded code point. -
iterator operator ++ (int);
- the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one. -
iterator& operator -- ();
the prefix decrement - moves - the iterator to the previous UTF-8 encoded code point. -
iterator operator -- (int);
- the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one. -
-

- Example of use: -

-
-char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
-utf8::unchecked::iterator<char*> un_it(threechars);
-utf8::unchecked::iterator<char*> un_it2 = un_it;
-assert (un_it2 == un_it);
-assert (*un_it == 0x10346);
-assert (*(++un_it) == 0x65e5);
-assert ((*un_it++) == 0x65e5);
-assert (*un_it == 0x0448);
-assert (un_it != un_it2);
-utf8::::unchecked::iterator<char*> un_endit (threechars + 9);  
-assert (++un_it == un_endit);
-assert (*(--un_it) == 0x0448);
-assert ((*un_it--) == 0x0448);
-assert (*un_it == 0x65e5);
-assert (--un_it == utf8::unchecked::iterator<char*>(threechars));
-assert (*un_it == 0x10346);
-
-

- This is an unchecked version of utf8::iterator. It is faster in many cases, but offers - no validity or range checks. -

-

- Points of interest -

-

- Design goals and decisions -

-

- The library was designed to be: -

-
    -
  1. - Generic: for better or worse, there are many C++ string classes out there, and - the library should work with as many of them as possible. -
  2. -
  3. - Portable: the library should be portable both accross different platforms and - compilers. The only non-portable code is a small section that declares unsigned - integers of different sizes: three typedefs. They can be changed by the users of - the library if they don't match their platform. The default setting should work - for Windows (both 32 and 64 bit), and most 32 bit and 64 bit Unix derivatives. -
  4. -
  5. - Lightweight: follow the "pay only for what you use" guideline. -
  6. -
  7. - Unintrusive: avoid forcing any particular design or even programming style on the - user. This is a library, not a framework. -
  8. -
-

- Alternatives -

-

- In case you want to look into other means of working with UTF-8 strings from C++, - here is the list of solutions I am aware of: -

-
    -
  1. - ICU Library. It is very powerful, - complete, feature-rich, mature, and widely used. Also big, intrusive, - non-generic, and doesn't play well with the Standard Library. I definitelly - recommend looking at ICU even if you don't plan to use it. -
  2. -
  3. - C++11 language and library features. Still far from complete, and not widely - supported by compiler vendors. -
  4. -
  5. - Glib::ustring. - A class specifically made to work with UTF-8 strings, and also feel like - std::string. If you prefer to have yet another string class in your - code, it may be worth a look. Be aware of the licensing issues, though. -
  6. -
  7. - Platform dependent solutions: Windows and POSIX have functions to convert strings - from one encoding to another. That is only a subset of what my library offers, - but if that is all you need it may be good enough. -
  8. -
- -
    -
  1. - The Unicode Consortium. -
  2. -
  3. - ICU Library. -
  4. -
  5. - UTF-8 at Wikipedia -
  6. -
  7. - UTF-8 and Unicode FAQ for - Unix/Linux -
  8. -
- - diff --git a/3rdparty/utf8/source/utf8.h b/3rdparty/utf8/source/utf8.h deleted file mode 100644 index 4e445140..00000000 --- a/3rdparty/utf8/source/utf8.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include "utf8/checked.h" -#include "utf8/unchecked.h" - -#endif // header guard diff --git a/3rdparty/utf8/source/utf8/checked.h b/3rdparty/utf8/source/utf8/checked.h deleted file mode 100644 index 13311551..00000000 --- a/3rdparty/utf8/source/utf8/checked.h +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include "core.h" -#include - -namespace utf8 -{ - // Base for the exceptions that may be thrown from the library - class exception : public ::std::exception { - }; - - // Exceptions that may be thrown from the library functions. - class invalid_code_point : public exception { - uint32_t cp; - public: - invalid_code_point(uint32_t cp) : cp(cp) {} - virtual const char* what() const throw() { return "Invalid code point"; } - uint32_t code_point() const {return cp;} - }; - - class invalid_utf8 : public exception { - uint8_t u8; - public: - invalid_utf8 (uint8_t u) : u8(u) {} - virtual const char* what() const throw() { return "Invalid UTF-8"; } - uint8_t utf8_octet() const {return u8;} - }; - - class invalid_utf16 : public exception { - uint16_t u16; - public: - invalid_utf16 (uint16_t u) : u16(u) {} - virtual const char* what() const throw() { return "Invalid UTF-16"; } - uint16_t utf16_word() const {return u16;} - }; - - class not_enough_room : public exception { - public: - virtual const char* what() const throw() { return "Not enough space"; } - }; - - /// The library API - functions intended to be called by the users - - template - octet_iterator append(uint32_t cp, octet_iterator result) - { - if (!utf8::internal::is_code_point_valid(cp)) - throw invalid_code_point(cp); - - if (cp < 0x80) // one octet - *(result++) = static_cast(cp); - else if (cp < 0x800) { // two octets - *(result++) = static_cast((cp >> 6) | 0xc0); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - else if (cp < 0x10000) { // three octets - *(result++) = static_cast((cp >> 12) | 0xe0); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - else { // four octets - *(result++) = static_cast((cp >> 18) | 0xf0); - *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - return result; - } - - template - output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) - { - while (start != end) { - octet_iterator sequence_start = start; - internal::utf_error err_code = utf8::internal::validate_next(start, end); - switch (err_code) { - case internal::UTF8_OK : - for (octet_iterator it = sequence_start; it != start; ++it) - *out++ = *it; - break; - case internal::NOT_ENOUGH_ROOM: - throw not_enough_room(); - case internal::INVALID_LEAD: - out = utf8::append (replacement, out); - ++start; - break; - case internal::INCOMPLETE_SEQUENCE: - case internal::OVERLONG_SEQUENCE: - case internal::INVALID_CODE_POINT: - out = utf8::append (replacement, out); - ++start; - // just one replacement mark for the sequence - while (start != end && utf8::internal::is_trail(*start)) - ++start; - break; - } - } - return out; - } - - template - inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) - { - static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd); - return utf8::replace_invalid(start, end, out, replacement_marker); - } - - template - uint32_t next(octet_iterator& it, octet_iterator end) - { - uint32_t cp = 0; - internal::utf_error err_code = utf8::internal::validate_next(it, end, cp); - switch (err_code) { - case internal::UTF8_OK : - break; - case internal::NOT_ENOUGH_ROOM : - throw not_enough_room(); - case internal::INVALID_LEAD : - case internal::INCOMPLETE_SEQUENCE : - case internal::OVERLONG_SEQUENCE : - throw invalid_utf8(*it); - case internal::INVALID_CODE_POINT : - throw invalid_code_point(cp); - } - return cp; - } - - template - uint32_t peek_next(octet_iterator it, octet_iterator end) - { - return utf8::next(it, end); - } - - template - uint32_t prior(octet_iterator& it, octet_iterator start) - { - // can't do much if it == start - if (it == start) - throw not_enough_room(); - - octet_iterator end = it; - // Go back until we hit either a lead octet or start - while (utf8::internal::is_trail(*(--it))) - if (it == start) - throw invalid_utf8(*it); // error - no lead byte in the sequence - return utf8::peek_next(it, end); - } - - /// Deprecated in versions that include "prior" - template - uint32_t previous(octet_iterator& it, octet_iterator pass_start) - { - octet_iterator end = it; - while (utf8::internal::is_trail(*(--it))) - if (it == pass_start) - throw invalid_utf8(*it); // error - no lead byte in the sequence - octet_iterator temp = it; - return utf8::next(temp, end); - } - - template - void advance (octet_iterator& it, distance_type n, octet_iterator end) - { - for (distance_type i = 0; i < n; ++i) - utf8::next(it, end); - } - - template - typename std::iterator_traits::difference_type - distance (octet_iterator first, octet_iterator last) - { - typename std::iterator_traits::difference_type dist; - for (dist = 0; first < last; ++dist) - utf8::next(first, last); - return dist; - } - - template - octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) - { - while (start != end) { - uint32_t cp = utf8::internal::mask16(*start++); - // Take care of surrogate pairs first - if (utf8::internal::is_lead_surrogate(cp)) { - if (start != end) { - uint32_t trail_surrogate = utf8::internal::mask16(*start++); - if (utf8::internal::is_trail_surrogate(trail_surrogate)) - cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; - else - throw invalid_utf16(static_cast(trail_surrogate)); - } - else - throw invalid_utf16(static_cast(cp)); - - } - // Lone trail surrogate - else if (utf8::internal::is_trail_surrogate(cp)) - throw invalid_utf16(static_cast(cp)); - - result = utf8::append(cp, result); - } - return result; - } - - template - u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) - { - while (start != end) { - uint32_t cp = utf8::next(start, end); - if (cp > 0xffff) { //make a surrogate pair - *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); - *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); - } - else - *result++ = static_cast(cp); - } - return result; - } - - template - octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) - { - while (start != end) - result = utf8::append(*(start++), result); - - return result; - } - - template - u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) - { - while (start != end) - (*result++) = utf8::next(start, end); - - return result; - } - - // The iterator class - template - class iterator : public std::iterator { - octet_iterator it; - octet_iterator range_start; - octet_iterator range_end; - public: - iterator () {} - explicit iterator (const octet_iterator& octet_it, - const octet_iterator& range_start, - const octet_iterator& range_end) : - it(octet_it), range_start(range_start), range_end(range_end) - { - if (it < range_start || it > range_end) - throw std::out_of_range("Invalid utf-8 iterator position"); - } - // the default "big three" are OK - octet_iterator base () const { return it; } - uint32_t operator * () const - { - octet_iterator temp = it; - return utf8::next(temp, range_end); - } - bool operator == (const iterator& rhs) const - { - if (range_start != rhs.range_start || range_end != rhs.range_end) - throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); - return (it == rhs.it); - } - bool operator != (const iterator& rhs) const - { - return !(operator == (rhs)); - } - iterator& operator ++ () - { - utf8::next(it, range_end); - return *this; - } - iterator operator ++ (int) - { - iterator temp = *this; - utf8::next(it, range_end); - return temp; - } - iterator& operator -- () - { - utf8::prior(it, range_start); - return *this; - } - iterator operator -- (int) - { - iterator temp = *this; - utf8::prior(it, range_start); - return temp; - } - }; // class iterator - -} // namespace utf8 - -#endif //header guard - - diff --git a/3rdparty/utf8/source/utf8/core.h b/3rdparty/utf8/source/utf8/core.h deleted file mode 100644 index 693d388c..00000000 --- a/3rdparty/utf8/source/utf8/core.h +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include - -namespace utf8 -{ - // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers - // You may need to change them to match your system. - // These typedefs have the same names as ones from cstdint, or boost/cstdint - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; - -// Helper code - not intended to be directly called by the library users. May be changed at any time -namespace internal -{ - // Unicode constants - // Leading (high) surrogates: 0xd800 - 0xdbff - // Trailing (low) surrogates: 0xdc00 - 0xdfff - const uint16_t LEAD_SURROGATE_MIN = 0xd800u; - const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; - const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; - const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; - const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10); - const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; - - // Maximum valid value for a Unicode code point - const uint32_t CODE_POINT_MAX = 0x0010ffffu; - - template - inline uint8_t mask8(octet_type oc) - { - return static_cast(0xff & oc); - } - template - inline uint16_t mask16(u16_type oc) - { - return static_cast(0xffff & oc); - } - template - inline bool is_trail(octet_type oc) - { - return ((utf8::internal::mask8(oc) >> 6) == 0x2); - } - - template - inline bool is_lead_surrogate(u16 cp) - { - return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); - } - - template - inline bool is_trail_surrogate(u16 cp) - { - return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); - } - - template - inline bool is_surrogate(u16 cp) - { - return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); - } - - template - inline bool is_code_point_valid(u32 cp) - { - return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp)); - } - - template - inline typename std::iterator_traits::difference_type - sequence_length(octet_iterator lead_it) - { - uint8_t lead = utf8::internal::mask8(*lead_it); - if (lead < 0x80) - return 1; - else if ((lead >> 5) == 0x6) - return 2; - else if ((lead >> 4) == 0xe) - return 3; - else if ((lead >> 3) == 0x1e) - return 4; - else - return 0; - } - - template - inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length) - { - if (cp < 0x80) { - if (length != 1) - return true; - } - else if (cp < 0x800) { - if (length != 2) - return true; - } - else if (cp < 0x10000) { - if (length != 3) - return true; - } - - return false; - } - - enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; - - /// Helper for get_sequence_x - template - utf_error increase_safely(octet_iterator& it, octet_iterator end) - { - if (++it == end) - return NOT_ENOUGH_ROOM; - - if (!utf8::internal::is_trail(*it)) - return INCOMPLETE_SEQUENCE; - - return UTF8_OK; - } - - #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;} - - /// get_sequence_x functions decode utf-8 sequences of the length x - template - utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); - - return UTF8_OK; - } - - template - utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); - - return UTF8_OK; - } - - template - utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point += (*it) & 0x3f; - - return UTF8_OK; - } - - template - utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point += (utf8::internal::mask8(*it) << 6) & 0xfff; - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point += (*it) & 0x3f; - - return UTF8_OK; - } - - #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR - - template - utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - // Save the original value of it so we can go back in case of failure - // Of course, it does not make much sense with i.e. stream iterators - octet_iterator original_it = it; - - uint32_t cp = 0; - // Determine the sequence length based on the lead octet - typedef typename std::iterator_traits::difference_type octet_difference_type; - const octet_difference_type length = utf8::internal::sequence_length(it); - - // Get trail octets and calculate the code point - utf_error err = UTF8_OK; - switch (length) { - case 0: - return INVALID_LEAD; - case 1: - err = utf8::internal::get_sequence_1(it, end, cp); - break; - case 2: - err = utf8::internal::get_sequence_2(it, end, cp); - break; - case 3: - err = utf8::internal::get_sequence_3(it, end, cp); - break; - case 4: - err = utf8::internal::get_sequence_4(it, end, cp); - break; - } - - if (err == UTF8_OK) { - // Decoding succeeded. Now, security checks... - if (utf8::internal::is_code_point_valid(cp)) { - if (!utf8::internal::is_overlong_sequence(cp, length)){ - // Passed! Return here. - code_point = cp; - ++it; - return UTF8_OK; - } - else - err = OVERLONG_SEQUENCE; - } - else - err = INVALID_CODE_POINT; - } - - // Failure branch - restore the original value of the iterator - it = original_it; - return err; - } - - template - inline utf_error validate_next(octet_iterator& it, octet_iterator end) { - uint32_t ignored; - return utf8::internal::validate_next(it, end, ignored); - } - -} // namespace internal - - /// The library API - functions intended to be called by the users - - // Byte order mark - const uint8_t bom[] = {0xef, 0xbb, 0xbf}; - - template - octet_iterator find_invalid(octet_iterator start, octet_iterator end) - { - octet_iterator result = start; - while (result != end) { - utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end); - if (err_code != internal::UTF8_OK) - return result; - } - return result; - } - - template - inline bool is_valid(octet_iterator start, octet_iterator end) - { - return (utf8::find_invalid(start, end) == end); - } - - template - inline bool starts_with_bom (octet_iterator it, octet_iterator end) - { - return ( - ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && - ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && - ((it != end) && (utf8::internal::mask8(*it)) == bom[2]) - ); - } - - //Deprecated in release 2.3 - template - inline bool is_bom (octet_iterator it) - { - return ( - (utf8::internal::mask8(*it++)) == bom[0] && - (utf8::internal::mask8(*it++)) == bom[1] && - (utf8::internal::mask8(*it)) == bom[2] - ); - } -} // namespace utf8 - -#endif // header guard - - diff --git a/3rdparty/utf8/source/utf8/unchecked.h b/3rdparty/utf8/source/utf8/unchecked.h deleted file mode 100644 index cb242716..00000000 --- a/3rdparty/utf8/source/utf8/unchecked.h +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include "core.h" - -namespace utf8 -{ - namespace unchecked - { - template - octet_iterator append(uint32_t cp, octet_iterator result) - { - if (cp < 0x80) // one octet - *(result++) = static_cast(cp); - else if (cp < 0x800) { // two octets - *(result++) = static_cast((cp >> 6) | 0xc0); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - else if (cp < 0x10000) { // three octets - *(result++) = static_cast((cp >> 12) | 0xe0); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - else { // four octets - *(result++) = static_cast((cp >> 18) | 0xf0); - *(result++) = static_cast(((cp >> 12) & 0x3f)| 0x80); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - return result; - } - - template - uint32_t next(octet_iterator& it) - { - uint32_t cp = utf8::internal::mask8(*it); - typename std::iterator_traits::difference_type length = utf8::internal::sequence_length(it); - switch (length) { - case 1: - break; - case 2: - it++; - cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); - break; - case 3: - ++it; - cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); - ++it; - cp += (*it) & 0x3f; - break; - case 4: - ++it; - cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); - ++it; - cp += (utf8::internal::mask8(*it) << 6) & 0xfff; - ++it; - cp += (*it) & 0x3f; - break; - } - ++it; - return cp; - } - - template - uint32_t peek_next(octet_iterator it) - { - return utf8::unchecked::next(it); - } - - template - uint32_t prior(octet_iterator& it) - { - while (utf8::internal::is_trail(*(--it))) ; - octet_iterator temp = it; - return utf8::unchecked::next(temp); - } - - // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous) - template - inline uint32_t previous(octet_iterator& it) - { - return utf8::unchecked::prior(it); - } - - template - void advance (octet_iterator& it, distance_type n) - { - for (distance_type i = 0; i < n; ++i) - utf8::unchecked::next(it); - } - - template - typename std::iterator_traits::difference_type - distance (octet_iterator first, octet_iterator last) - { - typename std::iterator_traits::difference_type dist; - for (dist = 0; first < last; ++dist) - utf8::unchecked::next(first); - return dist; - } - - template - octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) - { - while (start != end) { - uint32_t cp = utf8::internal::mask16(*start++); - // Take care of surrogate pairs first - if (utf8::internal::is_lead_surrogate(cp)) { - uint32_t trail_surrogate = utf8::internal::mask16(*start++); - cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; - } - result = utf8::unchecked::append(cp, result); - } - return result; - } - - template - u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) - { - while (start < end) { - uint32_t cp = utf8::unchecked::next(start); - if (cp > 0xffff) { //make a surrogate pair - *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); - *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); - } - else - *result++ = static_cast(cp); - } - return result; - } - - template - octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) - { - while (start != end) - result = utf8::unchecked::append(*(start++), result); - - return result; - } - - template - u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) - { - while (start < end) - (*result++) = utf8::unchecked::next(start); - - return result; - } - - // The iterator class - template - class iterator : public std::iterator { - octet_iterator it; - public: - iterator () {} - explicit iterator (const octet_iterator& octet_it): it(octet_it) {} - // the default "big three" are OK - octet_iterator base () const { return it; } - uint32_t operator * () const - { - octet_iterator temp = it; - return utf8::unchecked::next(temp); - } - bool operator == (const iterator& rhs) const - { - return (it == rhs.it); - } - bool operator != (const iterator& rhs) const - { - return !(operator == (rhs)); - } - iterator& operator ++ () - { - ::std::advance(it, utf8::internal::sequence_length(it)); - return *this; - } - iterator operator ++ (int) - { - iterator temp = *this; - ::std::advance(it, utf8::internal::sequence_length(it)); - return temp; - } - iterator& operator -- () - { - utf8::unchecked::prior(it); - return *this; - } - iterator operator -- (int) - { - iterator temp = *this; - utf8::unchecked::prior(it); - return temp; - } - }; // class iterator - - } // namespace utf8::unchecked -} // namespace utf8 - - -#endif // header guard - diff --git a/simgear/canvas/events/KeyboardEvent.cxx b/simgear/canvas/events/KeyboardEvent.cxx index 3c5c8eda..f5edbb09 100644 --- a/simgear/canvas/events/KeyboardEvent.cxx +++ b/simgear/canvas/events/KeyboardEvent.cxx @@ -19,7 +19,6 @@ #include #include "KeyboardEvent.hxx" -#include "utf8.h" #include @@ -42,6 +41,7 @@ namespace canvas // TODO check Win/Mac keycode for altgr/ISO Level3 Shift const uint32_t KEY_AltGraph = 0xfe03; + //---------------------------------------------------------------------------- KeyboardEvent::KeyboardEvent(): @@ -269,10 +269,24 @@ namespace canvas // Empty or no mapping -> convert UTF-32 key value to UTF-8 if( _name.empty() ) { - if( !utf8::internal::is_code_point_valid(_key) ) + if (( _key >= 0xd800u && _key <= 0xdfffu ) || _key > 0x10ffffu ) _name = "Unidentified"; else - utf8::unchecked::append(_key, std::back_inserter(_name)); + if ( _key <= 0x7f ) { + _name.push_back(static_cast(_key)); + } else if ( _key <= 0x7ff ) { + _name.push_back(static_cast((_key >> 6) | 0xc0)); + _name.push_back(static_cast((_key & 0x3f) | 0x80)); + } else if ( _key <= 0xffff ) { + _name.push_back(static_cast((_key >> 12) | 0xe0)); + _name.push_back(static_cast(((_key >> 6) & 0x3f) | 0x80)); + _name.push_back(static_cast((_key & 0x3f) | 0x80)); + } else { + _name.push_back(static_cast((_key >> 18) | 0xf0)); + _name.push_back(static_cast(((_key >> 12) & 0x3f) | 0x80)); + _name.push_back(static_cast(((_key >> 6) & 0x3f) | 0x80)); + _name.push_back(static_cast((_key & 0x3f) | 0x80)); + } } // Keys on the numpad with NumLock enabled are reported just like their @@ -307,11 +321,30 @@ namespace canvas if( key_name.empty() ) return false; - std::string::const_iterator it = key_name.begin(); - uint32_t cp = utf8::next(it, key_name.end()); + // Convert the key name to the corresponding code point by checking the + // sequence length (the first bits of the first byte) and performing the + // conversion accordingly. + uint32_t cp = key_name[0] & 0xff; + size_t len; + if (cp < 0x80) { + len = 1; + } else if ((cp >> 5) == 0x6) { + cp = ((cp << 6) & 0x7ff) + (key_name[1] & 0x3f); + len = 2; + } else if ((cp >> 4) == 0xe) { + cp = ((cp << 12) & 0xffff) + (((key_name[1] & 0xff) << 6) & 0xfff) + + (key_name[2] & 0x3f); + len = 3; + } else if ((cp >> 3) == 0x1e) { + cp = ((cp << 18) & 0x1fffff) + (((key_name[1] & 0xff) << 12) & 0x3ffff) + + (((key_name[2] & 0xff) << 6) & 0xfff) + (key_name[3] & 0x3f); + len = 4; + } else { + return false; + } // Check if _name contains exactly one (UTF-8 encoded) character. - if( it != key_name.end() ) + if (key_name.length() > len) return false; // C0 and C1 control characters are not printable. From ddb7958f40edf83fd82c2b502a3bf3d65447c02e Mon Sep 17 00:00:00 2001 From: Alessandro Menti Date: Sat, 2 Dec 2017 17:47:05 +0100 Subject: [PATCH 11/18] Remove old .spec files Remove old SuSE/Red Hat packaging files (in line with what was done in commit ef66ba in FlightGear). --- package/RedHat/README | 13 -------- package/openSUSE/README | 23 ------------- package/openSUSE/SimGear.spec | 63 ----------------------------------- 3 files changed, 99 deletions(-) delete mode 100644 package/RedHat/README delete mode 100644 package/openSUSE/README delete mode 100644 package/openSUSE/SimGear.spec diff --git a/package/RedHat/README b/package/RedHat/README deleted file mode 100644 index e034f938..00000000 --- a/package/RedHat/README +++ /dev/null @@ -1,13 +0,0 @@ -Building a SimGear RPM package for Red Hat - -Please see the "package/openSUSE" directory for an -example how to build a SimGear RPM package with -shared SimGear libraries. - -You may need to adapt the names (exact spelling) of some -of the package dependencies in the openSUSE RPM spec, -since these may slightly differ for Red Hat. - -(If you have a working and tested Red Hat RPM spec, -you're welcome to contribute it to this project.) - diff --git a/package/openSUSE/README b/package/openSUSE/README deleted file mode 100644 index 11517209..00000000 --- a/package/openSUSE/README +++ /dev/null @@ -1,23 +0,0 @@ -Building a SimGear RPM package for openSUSE - -(Last tested with openSUSE 11.4+12.1) - -This directory contains the files which, along with -the source code tar files, can be used to build -an RPM package targeted at an openSUSE Linux system. - -To build SimGear from source do the following: - -1. obtain simgear-2.8.0.tar.bz2 (adapt version if - necessary) and copy it into ~/rpmbuild/SOURCES - -2. look in the BuildRequires section of SimGear.spec - and check that all the packages referred to are - installed (note, some of these packages may be part - of openSUSE's "games" repository). - -3. run 'rpmbuild -ba simgear.spec' and find the RPM - build result in ~/rpmbuild/RPMS - -That's all! - diff --git a/package/openSUSE/SimGear.spec b/package/openSUSE/SimGear.spec deleted file mode 100644 index 2fc0621a..00000000 --- a/package/openSUSE/SimGear.spec +++ /dev/null @@ -1,63 +0,0 @@ -Summary: Simulator Construction Gear -Name: SimGear -Version: 2.8.0 -Release: 1 -License: LGPL -URL: http://www.flightgear.org -Group: Amusements/Games/3D/Simulation -Source: http://mirrors.ibiblio.org/pub/mirrors/flightgear/ftp/Source/simgear-%{version}.tar.bz2 -BuildRoot: %{_tmppath}/%{name}-%{version}-build - -BuildRequires: gcc, gcc-c++, cmake -BuildRequires: libopenal1-soft, openal-soft -BuildRequires: libOpenSceneGraph-devel >= 3.0 -BuildRequires: zlib, zlib-devel -BuildRequires: libjpeg62, libjpeg62-devel -BuildRequires: boost-devel >= 1.37 -BuildRequires: subversion-devel, libapr1-devel -Requires: OpenSceneGraph-plugins >= 3.0 - -%description -This package contains a tools and libraries useful for constructing -simulation and visualization applications such as FlightGear or TerraGear. - -%package devel -Group: Development/Libraries/Other -Summary: Development header files for SimGear -Requires: SimGear = %{version} - -%description devel -Development headers and libraries for building applications against SimGear. - -%prep -%setup -T -q -n simgear-%{version} -b 0 - -%build -export CFLAGS="$RPM_OPT_FLAGS" -export CXXFLAGS="$RPM_OPT_FLAGS" -# build SHARED simgear libraries -cmake -DCMAKE_INSTALL_PREFIX=%{_prefix} -DSIMGEAR_SHARED:BOOL=ON -DENABLE_TESTS:BOOL=OFF -DJPEG_FACTORY:BOOL=ON -make %{?_smp_mflags} - -%install -make DESTDIR=%{buildroot} install - -%post -p /sbin/ldconfig - -%postun -p /sbin/ldconfig - -%files -%defattr (-, root, root, -) -%doc AUTHORS COPYING ChangeLog NEWS README -%{_libdir}/libSimGear*.so.* - -%files devel -%defattr(-,root,root,-) -%dir %{_includedir}/simgear -%{_includedir}/simgear/* -%{_libdir}/libSimGear*.so - -%changelog -* Mon Jul 02 2012 thorstenb@flightgear.org -- Initial version - From 854881bba258378ba90c3f9de29496c5fd650d16 Mon Sep 17 00:00:00 2001 From: Richard Harrison Date: Mon, 4 Dec 2017 07:30:48 +0100 Subject: [PATCH 12/18] Prevent nullptr exception. Had this happen once. --- simgear/canvas/elements/CanvasGroup.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/simgear/canvas/elements/CanvasGroup.cxx b/simgear/canvas/elements/CanvasGroup.cxx index c753c2e2..d398fe2e 100644 --- a/simgear/canvas/elements/CanvasGroup.cxx +++ b/simgear/canvas/elements/CanvasGroup.cxx @@ -387,7 +387,9 @@ namespace canvas OSGUserData* ud = static_cast(_transform->getChild(index)->getUserData()); assert(ud); - return ud->element; + if (ud) + return ud->element; + return nullptr; } //---------------------------------------------------------------------------- From 7dcc359110f5d3c61e92ecfc112503f1bc44eff1 Mon Sep 17 00:00:00 2001 From: Richard Harrison Date: Mon, 4 Dec 2017 07:31:59 +0100 Subject: [PATCH 13/18] add condition to pick animations --- simgear/scene/model/SGPickAnimation.cxx | 124 ++++++++++++++---------- simgear/scene/model/SGPickAnimation.hxx | 3 +- 2 files changed, 76 insertions(+), 51 deletions(-) diff --git a/simgear/scene/model/SGPickAnimation.cxx b/simgear/scene/model/SGPickAnimation.cxx index 3fa643d6..ae99eb29 100644 --- a/simgear/scene/model/SGPickAnimation.cxx +++ b/simgear/scene/model/SGPickAnimation.cxx @@ -74,10 +74,12 @@ osg::Vec2d eventToWindowCoords(const osgGA::GUIEventAdapter& ea) class SGPickAnimation::PickCallback : public SGPickCallback { public: PickCallback(const SGPropertyNode* configNode, - SGPropertyNode* modelRoot) : + SGPropertyNode* modelRoot, + SGSharedPtr condition) : SGPickCallback(PriorityPanel), _repeatable(configNode->getBoolValue("repeatable", false)), - _repeatInterval(configNode->getDoubleValue("interval-sec", 0.1)) + _repeatInterval(configNode->getDoubleValue("interval-sec", 0.1)), + _condition(condition) { std::vector bindings; @@ -98,63 +100,76 @@ osg::Vec2d eventToWindowCoords(const osgGA::GUIEventAdapter& ea) void addHoverBindings(const SGPropertyNode* hoverNode, SGPropertyNode* modelRoot) { - _hover = readBindingList(hoverNode->getChildren("binding"), modelRoot); + if (!_condition || _condition->test()) { + _hover = readBindingList(hoverNode->getChildren("binding"), modelRoot); + } } virtual bool buttonPressed( int button, const osgGA::GUIEventAdapter&, const Info& ) { - if (_buttons.find(button) == _buttons.end()) { - return false; - } + if (!_condition || _condition->test()) { + if (_buttons.find(button) == _buttons.end()) { + return false; + } - if (!anyBindingEnabled(_bindingsDown)) { - return false; - } + if (!anyBindingEnabled(_bindingsDown)) { + return false; + } - fireBindingList(_bindingsDown); - _repeatTime = -_repeatInterval; // anti-bobble: delay start of repeat - return true; + fireBindingList(_bindingsDown); + _repeatTime = -_repeatInterval; // anti-bobble: delay start of repeat + return true; + } + return false; } virtual void buttonReleased( int keyModState, const osgGA::GUIEventAdapter&, const Info* ) { - SG_UNUSED(keyModState); - fireBindingList(_bindingsUp); + if (!_condition || _condition->test()) { + SG_UNUSED(keyModState); + fireBindingList(_bindingsUp); + } } virtual void update(double dt, int keyModState) { - SG_UNUSED(keyModState); - if (!_repeatable) - return; + if (!_condition || _condition->test()) { + SG_UNUSED(keyModState); + if (!_repeatable) + return; - _repeatTime += dt; - while (_repeatInterval < _repeatTime) { - _repeatTime -= _repeatInterval; - fireBindingList(_bindingsDown); - } + _repeatTime += dt; + while (_repeatInterval < _repeatTime) { + _repeatTime -= _repeatInterval; + fireBindingList(_bindingsDown); + } + } } virtual bool hover( const osg::Vec2d& windowPos, const Info& ) { - if (!anyBindingEnabled(_hover)) { - return false; + if (!_condition || _condition->test()) { + if (!anyBindingEnabled(_hover)) { + return false; + } + + SGPropertyNode_ptr params(new SGPropertyNode); + params->setDoubleValue("x", windowPos.x()); + params->setDoubleValue("y", windowPos.y()); + fireBindingList(_hover, params.ptr()); + return true; } - - SGPropertyNode_ptr params(new SGPropertyNode); - params->setDoubleValue("x", windowPos.x()); - params->setDoubleValue("y", windowPos.y()); - fireBindingList(_hover, params.ptr()); - return true; + return false; } std::string getCursor() const { return _cursorName; } private: + SGSharedPtr _condition; SGBindingList _bindingsDown; SGBindingList _bindingsUp; SGBindingList _hover; @@ -247,8 +262,9 @@ class SGPickAnimation::VncCallback : public SGPickCallback { public: VncCallback(const SGPropertyNode* configNode, SGPropertyNode* modelRoot, - osg::Group *node) - : _node(node) + osg::Group *node, + SGSharedPtr condition) + : _node(node), _condition(condition) { SG_LOG(SG_INPUT, SG_DEBUG, "Configuring VNC callback"); const char *cornernames[3] = {"top-left", "top-right", "bottom-left"}; @@ -270,29 +286,35 @@ public: const osgGA::GUIEventAdapter&, const Info& info ) { - SGVec3d loc(info.local); - SG_LOG(SG_INPUT, SG_DEBUG, "VNC pressed " << button << ": " << loc); - loc -= _topLeft; - _x = dot(loc, _toRight) / _squaredRight; - _y = dot(loc, _toDown) / _squaredDown; - if (_x<0) _x = 0; else if (_x > 1) _x = 1; - if (_y<0) _y = 0; else if (_y > 1) _y = 1; - VncVisitor vv(_x, _y, 1 << button); - _node->accept(vv); - return vv.wasSuccessful(); - + if (!_condition || _condition->test()) { + SGVec3d loc(info.local); + SG_LOG(SG_INPUT, SG_DEBUG, "VNC pressed " << button << ": " << loc); + loc -= _topLeft; + _x = dot(loc, _toRight) / _squaredRight; + _y = dot(loc, _toDown) / _squaredDown; + if (_x < 0) _x = 0; else if (_x > 1) _x = 1; + if (_y < 0) _y = 0; else if (_y > 1) _y = 1; + VncVisitor vv(_x, _y, 1 << button); + _node->accept(vv); + return vv.wasSuccessful(); + } + return false; } virtual void buttonReleased( int keyModState, const osgGA::GUIEventAdapter&, const Info* ) { - SG_UNUSED(keyModState); - SG_LOG(SG_INPUT, SG_DEBUG, "VNC release"); - VncVisitor vv(_x, _y, 0); - _node->accept(vv); + if (!_condition || _condition->test()) { + SG_UNUSED(keyModState); + SG_LOG(SG_INPUT, SG_DEBUG, "VNC release"); + VncVisitor vv(_x, _y, 0); + _node->accept(vv); + } } private: + SGSharedPtr _condition; + double _x, _y; osg::ref_ptr _node; SGVec3d _topLeft, _toRight, _toDown; @@ -304,6 +326,8 @@ private: SGPickAnimation::SGPickAnimation(simgear::SGTransientModelData &modelData) : SGAnimation(modelData) { + _condition = getCondition(); + std::vector names = modelData.getConfigNode()->getChildren("proxy-name"); for (unsigned i = 0; i < names.size(); ++i) { _proxyNames.push_back(names[i]->getStringValue()); @@ -451,7 +475,7 @@ SGPickAnimation::setupCallbacks(SGSceneUserData* ud, osg::Group* parent) std::vector actions; actions = getConfig()->getChildren("action"); for (unsigned int i = 0; i < actions.size(); ++i) { - pickCb = new PickCallback(actions[i], getModelRoot()); + pickCb = new PickCallback(actions[i], getModelRoot(), _condition); ud->addPickCallback(pickCb); } @@ -459,7 +483,7 @@ SGPickAnimation::setupCallbacks(SGSceneUserData* ud, osg::Group* parent) if (!pickCb) { // make a trivial PickCallback to hang the hovered off of SGPropertyNode_ptr dummyNode(new SGPropertyNode); - pickCb = new PickCallback(dummyNode.ptr(), getModelRoot()); + pickCb = new PickCallback(dummyNode.ptr(), getModelRoot(), _condition); ud->addPickCallback(pickCb); } @@ -469,7 +493,7 @@ SGPickAnimation::setupCallbacks(SGSceneUserData* ud, osg::Group* parent) // Look for the VNC sessions that want raw mouse input actions = getConfig()->getChildren("vncaction"); for (unsigned int i = 0; i < actions.size(); ++i) { - ud->addPickCallback(new VncCallback(actions[i], getModelRoot(), parent)); + ud->addPickCallback(new VncCallback(actions[i], getModelRoot(), parent, _condition)); } } diff --git a/simgear/scene/model/SGPickAnimation.hxx b/simgear/scene/model/SGPickAnimation.hxx index 00695467..63fc4999 100644 --- a/simgear/scene/model/SGPickAnimation.hxx +++ b/simgear/scene/model/SGPickAnimation.hxx @@ -45,7 +45,8 @@ protected: virtual osg::Group* createMainGroup(osg::Group* pr); - + SGSharedPtr _condition; + virtual void setupCallbacks(SGSceneUserData* ud, osg::Group* parent); private: class PickCallback; From 8d3723c91fe56e63edaeb498e9f71e7db5f7629b Mon Sep 17 00:00:00 2001 From: Richard Harrison Date: Mon, 4 Dec 2017 07:33:45 +0100 Subject: [PATCH 14/18] Prevent nullptr exception in treenodes. Happened to me once or twice mainly during reposition probably as scenery changed whilst still loading. --- simgear/scene/tgdb/TreeBin.cxx | 48 ++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/simgear/scene/tgdb/TreeBin.cxx b/simgear/scene/tgdb/TreeBin.cxx index 7c6bc990..ee8f4b39 100644 --- a/simgear/scene/tgdb/TreeBin.cxx +++ b/simgear/scene/tgdb/TreeBin.cxx @@ -202,33 +202,41 @@ void addTreeToLeafGeode(Geode* geode, const SGVec3f& p, const SGVec3f& t) Vec3 pos = toOsg(p); Vec3 ter = toOsg(t); unsigned int numDrawables = geode->getNumDrawables(); - Geometry* geom - = static_cast(geode->getDrawable(numDrawables - 1)); + Geometry* geom = static_cast(geode->getDrawable(numDrawables - 1)); Vec3Array* posArray = static_cast(geom->getColorArray()); Vec3Array* tnormalArray = NULL; - if (use_tree_shadows || use_tree_normals) - {tnormalArray = static_cast(geom->getSecondaryColorArray());} - if (posArray->size() - >= static_cast(geom->getVertexArray())->size()) { - Vec3Array* paramsArray - = static_cast(geom->getNormalArray()); + + if (use_tree_shadows || use_tree_normals) { + tnormalArray = static_cast(geom->getSecondaryColorArray()); + } + + if (posArray->size() >= static_cast(geom->getVertexArray())->size()) { + Vec3Array* paramsArray = static_cast(geom->getNormalArray()); Vec3 params = (*paramsArray)[0]; geom = createTreeGeometry(params.x(), params.y(), params.z()); posArray = static_cast(geom->getColorArray()); - if (use_tree_shadows || use_tree_normals) - {tnormalArray = static_cast(geom->getSecondaryColorArray());} + + if (use_tree_shadows || use_tree_normals) { + tnormalArray = static_cast(geom->getSecondaryColorArray()); + } geode->addDrawable(geom); } - posArray->insert(posArray->end(), 4, pos); - if (use_tree_shadows || use_tree_normals) - {tnormalArray->insert(tnormalArray->end(),4,ter);} - size_t numVerts = posArray->size(); - int imax = 2; - if (use_tree_shadows) {imax = 3;} - for (int i = 0; i < imax; ++i) { - DrawArrays* primSet - = static_cast(geom->getPrimitiveSet(i)); - primSet->setCount(numVerts); + + if (tnormalArray && (use_tree_shadows || use_tree_normals)) + tnormalArray->insert(tnormalArray->end(), 4, ter); + + if (posArray) + { + posArray->insert(posArray->end(), 4, pos); + + size_t numVerts = posArray->size(); + int imax = 2; + if (use_tree_shadows) { imax = 3; } + for (int i = 0; i < imax; ++i) { + DrawArrays* primSet = static_cast(geom->getPrimitiveSet(i)); + if(primSet != nullptr) + primSet->setCount(numVerts); + } } } From 1f12966628504a7ab29fe19f92c7db94f91523e8 Mon Sep 17 00:00:00 2001 From: Richard Harrison Date: Mon, 4 Dec 2017 07:53:39 +0100 Subject: [PATCH 15/18] Add condition to knob animation. This will prevent both input from being received and the position being updated by property change. --- simgear/scene/model/SGPickAnimation.cxx | 175 ++++++++++++++---------- simgear/scene/model/SGPickAnimation.hxx | 3 +- 2 files changed, 102 insertions(+), 76 deletions(-) diff --git a/simgear/scene/model/SGPickAnimation.cxx b/simgear/scene/model/SGPickAnimation.cxx index ae99eb29..e5408007 100644 --- a/simgear/scene/model/SGPickAnimation.cxx +++ b/simgear/scene/model/SGPickAnimation.cxx @@ -532,11 +532,13 @@ public: KnobSliderPickCallback(const SGPropertyNode* configNode, - SGPropertyNode* modelRoot) : + SGPropertyNode* modelRoot, + SGSharedPtr condition) : SGPickCallback(PriorityPanel), _direction(DIRECTION_NONE), _repeatInterval(configNode->getDoubleValue("interval-sec", 0.1)), - _dragDirection(DRAG_DEFAULT) + _dragDirection(DRAG_DEFAULT), + _condition(condition) { readOptionalBindingList(configNode, modelRoot, "action", _action); readOptionalBindingList(configNode, modelRoot, "increase", _bindingsIncrease); @@ -584,41 +586,49 @@ public: const osgGA::GUIEventAdapter& ea, const Info& ) { - // the 'be nice to Mac / laptop' users option; alt-clicking spins the + if (!_condition || _condition->test()) { + // the 'be nice to Mac / laptop' users option; alt-clicking spins the // opposite direction. Should make this configurable - if ((button == 0) && (ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_ALT)) { - button = 1; + if ((button == 0) && (ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_ALT)) { + button = 1; + } + + int increaseMouseWheel = static_knobMouseWheelAlternateDirection ? 3 : 4; + int decreaseMouseWheel = static_knobMouseWheelAlternateDirection ? 4 : 3; + + _direction = DIRECTION_NONE; + if ((button == 0) || (button == increaseMouseWheel)) { + _direction = DIRECTION_INCREASE; + } + else if ((button == 1) || (button == decreaseMouseWheel)) { + _direction = DIRECTION_DECREASE; + } + else { + return false; + } + + _lastFirePos = eventToWindowCoords(ea); + // delay start of repeat, makes dragging more usable + _repeatTime = -_repeatInterval; + _hasDragged = false; + return true; } - - int increaseMouseWheel = static_knobMouseWheelAlternateDirection ? 3 : 4; - int decreaseMouseWheel = static_knobMouseWheelAlternateDirection ? 4 : 3; - - _direction = DIRECTION_NONE; - if ((button == 0) || (button == increaseMouseWheel)) { - _direction = DIRECTION_INCREASE; - } else if ((button == 1) || (button == decreaseMouseWheel)) { - _direction = DIRECTION_DECREASE; - } else { - return false; - } - - _lastFirePos = eventToWindowCoords(ea); - // delay start of repeat, makes dragging more usable - _repeatTime = -_repeatInterval; - _hasDragged = false; - return true; + return false; } virtual void buttonReleased( int keyModState, const osgGA::GUIEventAdapter&, const Info* ) { - // for *clicks*, we only fire on button release - if (!_hasDragged) { - fire(keyModState & osgGA::GUIEventAdapter::MODKEY_SHIFT, _direction); + if (!_condition || _condition->test()) { + + // for *clicks*, we only fire on button release + if (!_hasDragged) { + fire(keyModState & osgGA::GUIEventAdapter::MODKEY_SHIFT, _direction); + } + + fireBindingList(_releaseAction); } - - fireBindingList(_releaseAction); } DragDirection effectiveDragDirection() const @@ -635,32 +645,34 @@ public: virtual void mouseMoved( const osgGA::GUIEventAdapter& ea, const Info* ) { - _mousePos = eventToWindowCoords(ea); - osg::Vec2d deltaMouse = _mousePos - _lastFirePos; - - if (!_hasDragged) { - - double manhattanDist = deltaMouse.x() * deltaMouse.x() + deltaMouse.y() * deltaMouse.y(); - if (manhattanDist < 5) { - // don't do anything, just input noise - return; + if (!_condition || _condition->test()) { + _mousePos = eventToWindowCoords(ea); + osg::Vec2d deltaMouse = _mousePos - _lastFirePos; + + if (!_hasDragged) { + + double manhattanDist = deltaMouse.x() * deltaMouse.x() + deltaMouse.y() * deltaMouse.y(); + if (manhattanDist < 5) { + // don't do anything, just input noise + return; + } + + // user is dragging, disable repeat behaviour + _hasDragged = true; + } + + double delta = (effectiveDragDirection() == DRAG_VERTICAL) ? deltaMouse.y() : deltaMouse.x(); + // per-animation scale factor lets the aircraft author tune for expectations, + // eg heading setting vs 5-state switch. + // then we scale by a global sensitivity, which the user can set. + delta *= static_dragSensitivity / _dragScale; + + if (fabs(delta) >= 1.0) { + // determine direction from sign of delta + Direction dir = (delta > 0.0) ? DIRECTION_INCREASE : DIRECTION_DECREASE; + fire(ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_SHIFT, dir); + _lastFirePos = _mousePos; } - - // user is dragging, disable repeat behaviour - _hasDragged = true; - } - - double delta = (effectiveDragDirection() == DRAG_VERTICAL) ? deltaMouse.y() : deltaMouse.x(); - // per-animation scale factor lets the aircraft author tune for expectations, - // eg heading setting vs 5-state switch. - // then we scale by a global sensitivity, which the user can set. - delta *= static_dragSensitivity / _dragScale; - - if (fabs(delta) >= 1.0) { - // determine direction from sign of delta - Direction dir = (delta > 0.0) ? DIRECTION_INCREASE : DIRECTION_DECREASE; - fire(ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_SHIFT, dir); - _lastFirePos = _mousePos; } } @@ -680,15 +692,19 @@ public: virtual bool hover( const osg::Vec2d& windowPos, const Info& ) { - if (_hover.empty()) { - return false; + if (!_condition || _condition->test()) { + + if (_hover.empty()) { + return false; + } + + SGPropertyNode_ptr params(new SGPropertyNode); + params->setDoubleValue("x", windowPos.x()); + params->setDoubleValue("y", windowPos.y()); + fireBindingList(_hover, params.ptr()); + return true; } - - SGPropertyNode_ptr params(new SGPropertyNode); - params->setDoubleValue("x", windowPos.x()); - params->setDoubleValue("y", windowPos.y()); - fireBindingList(_hover, params.ptr()); - return true; + return false; } void setCursor(const std::string& aName) @@ -702,13 +718,15 @@ public: private: void fire(bool isShifted, Direction dir) { - const SGBindingList& act(isShifted ? _shiftedAction : _action); - const SGBindingList& incr(isShifted ? _shiftedIncrease : _bindingsIncrease); - const SGBindingList& decr(isShifted ? _shiftedDecrease : _bindingsDecrease); - - switch (dir) { + if (!_condition || _condition->test()) { + + const SGBindingList& act(isShifted ? _shiftedAction : _action); + const SGBindingList& incr(isShifted ? _shiftedIncrease : _bindingsIncrease); + const SGBindingList& decr(isShifted ? _shiftedDecrease : _bindingsDecrease); + + switch (dir) { case DIRECTION_INCREASE: - fireBindingListWithOffset(act, 1, 1); + fireBindingListWithOffset(act, 1, 1); fireBindingList(incr); break; case DIRECTION_DECREASE: @@ -716,6 +734,7 @@ private: fireBindingList(decr); break; default: break; + } } } @@ -731,6 +750,8 @@ private: double _repeatTime; DragDirection _dragDirection; + SGSharedPtr _condition; + bool _hasDragged; ///< has the mouse been dragged since the press? osg::Vec2d _mousePos, ///< current window coords location of the mouse _lastFirePos; ///< mouse location where we last fired the bindings @@ -743,19 +764,22 @@ private: class SGKnobAnimation::UpdateCallback : public osg::NodeCallback { public: - UpdateCallback(SGExpressiond const* animationValue) : - _animationValue(animationValue) + UpdateCallback(SGExpressiond const* animationValue, SGSharedPtr condition) : + _animationValue(animationValue), _condition(condition) { setName("SGKnobAnimation::UpdateCallback"); } virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) { - SGRotateTransform* transform = static_cast(node); - transform->setAngleDeg(_animationValue->getValue()); - traverse(node, nv); + if (!_condition || _condition->test()) { + SGRotateTransform* transform = static_cast(node); + transform->setAngleDeg(_animationValue->getValue()); + traverse(node, nv); + } } private: + SGSharedPtr _condition; SGSharedPtr _animationValue; }; @@ -763,6 +787,7 @@ private: SGKnobAnimation::SGKnobAnimation(simgear::SGTransientModelData &modelData) : SGPickAnimation(modelData) { + _condition = getCondition(); SGSharedPtr value = read_value(modelData.getConfigNode(), modelData.getModelRoot(), "-deg", -SGLimitsd::max(), SGLimitsd::max()); _animationValue = value->simplify(); @@ -776,7 +801,7 @@ SGKnobAnimation::createMainGroup(osg::Group* pr) { SGRotateTransform* transform = new SGRotateTransform(); - UpdateCallback* uc = new UpdateCallback(_animationValue); + UpdateCallback* uc = new UpdateCallback(_animationValue, _condition); transform->setUpdateCallback(uc); transform->setCenter(_center); transform->setAxis(_axis); @@ -788,7 +813,7 @@ SGKnobAnimation::createMainGroup(osg::Group* pr) void SGKnobAnimation::setupCallbacks(SGSceneUserData* ud, osg::Group*) { - ud->setPickCallback(new KnobSliderPickCallback(getConfig(), getModelRoot())); + ud->setPickCallback(new KnobSliderPickCallback(getConfig(), getModelRoot(), _condition)); } void SGKnobAnimation::setAlternateMouseWheelDirection(bool aToggle) @@ -854,7 +879,7 @@ SGSliderAnimation::createMainGroup(osg::Group* pr) void SGSliderAnimation::setupCallbacks(SGSceneUserData* ud, osg::Group*) { - ud->setPickCallback(new KnobSliderPickCallback(getConfig(), getModelRoot())); + ud->setPickCallback(new KnobSliderPickCallback(getConfig(), getModelRoot(), _condition)); } /* diff --git a/simgear/scene/model/SGPickAnimation.hxx b/simgear/scene/model/SGPickAnimation.hxx index 63fc4999..4230f7a5 100644 --- a/simgear/scene/model/SGPickAnimation.hxx +++ b/simgear/scene/model/SGPickAnimation.hxx @@ -86,7 +86,8 @@ public: protected: virtual osg::Group* createMainGroup(osg::Group* pr); - + SGSharedPtr _condition; + virtual void setupCallbacks(SGSceneUserData* ud, osg::Group* parent); private: From 68053d64b548a9613c15132913b2dfc6cd510f44 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Mon, 4 Dec 2017 07:50:47 +0100 Subject: [PATCH 16/18] function_list<>: Simplify with C++11 --- simgear/structure/CMakeLists.txt | 5 --- .../detail/function_list_template.hxx | 37 ---------------- simgear/structure/function_list.hxx | 42 ++++++++++++------- 3 files changed, 26 insertions(+), 58 deletions(-) delete mode 100644 simgear/structure/detail/function_list_template.hxx diff --git a/simgear/structure/CMakeLists.txt b/simgear/structure/CMakeLists.txt index 9d25d3d7..7c7df4f3 100644 --- a/simgear/structure/CMakeLists.txt +++ b/simgear/structure/CMakeLists.txt @@ -28,10 +28,6 @@ set(HEADERS StateMachine.hxx ) -set(DETAIL_HEADERS - detail/function_list_template.hxx -) - set(SOURCES SGAtomic.cxx SGBinding.cxx @@ -48,7 +44,6 @@ set(SOURCES ) simgear_component(structure structure "${SOURCES}" "${HEADERS}") -simgear_component(structure/detail structure/detail "" "${DETAIL_HEADERS}") if(ENABLE_TESTS) diff --git a/simgear/structure/detail/function_list_template.hxx b/simgear/structure/detail/function_list_template.hxx deleted file mode 100644 index 92a10a27..00000000 --- a/simgear/structure/detail/function_list_template.hxx +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SG_FUNCTION_LIST_HXX_ -# error function_list - do not include this file! -#endif - -#ifndef SG_DONT_DO_ANYTHING -#define n BOOST_PP_ITERATION() -#define SG_FUNC_TYPE boost::function -#define SG_LIST_TYPE std::vector - -template -class function_list: - public SG_LIST_TYPE -{ - public: - typedef SG_FUNC_TYPE function_type; - typedef typename SG_LIST_TYPE::iterator iterator; - typedef typename SG_LIST_TYPE::const_iterator const_iterator; - - Ret operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, A, a)) const - { - if( this->empty() ) - return Ret(); - - const_iterator list_end = --this->end(); - for(const_iterator f = this->begin(); f != list_end; ++f) - if( *f ) - (*f)(BOOST_PP_ENUM_PARAMS(n, a)); - - return (*list_end) ? (*list_end)(BOOST_PP_ENUM_PARAMS(n, a)) : Ret(); - } -}; - -#undef n -#undef SG_FUNC_TYPE -#undef SG_LIST_TYPE - -#endif // SG_DONT_DO_ANYTHING diff --git a/simgear/structure/function_list.hxx b/simgear/structure/function_list.hxx index 314c16ed..5268d2ca 100644 --- a/simgear/structure/function_list.hxx +++ b/simgear/structure/function_list.hxx @@ -20,33 +20,43 @@ #define SG_FUNCTION_LIST_HXX_ #include -#include -#include -#include -#include #include namespace simgear { template class function_list; - // Build dependency for CMake, gcc, etc. -# define SG_DONT_DO_ANYTHING -# include -# undef SG_DONT_DO_ANYTHING - -# define BOOST_PP_ITERATION_LIMITS (0, 3) -# define BOOST_PP_FILENAME_1 -# include BOOST_PP_ITERATE() - /** * Handle a list of callbacks like a single boost::function. * * @tparam Sig Function signature. */ - template - class function_list >: - public function_list + template + class function_list: + public std::vector> + { + public: + Ret operator()(Args ... args) const + { + if( this->empty() ) + return Ret(); + + auto list_end = --this->end(); + for(auto f = this->begin(); f != list_end; ++f) + if( *f ) + (*f)(args...); + + return (*list_end) ? (*list_end)(args...) : Ret(); + } + }; + + /** + * Handle a list of callbacks with the same signature as the given + * boost::function type. + */ + template + class function_list>: + public function_list { }; From f6ded69fa34a52abe2f217692ba8d7722b06ab31 Mon Sep 17 00:00:00 2001 From: James Turner Date: Mon, 11 Dec 2017 18:14:40 +0000 Subject: [PATCH 17/18] Untar failure path fixes By xDraconian, ensure we call inflateEnd in failure cases, otherwise the inflate context is leaked. --- simgear/io/test_untar.cxx | 6 ++++-- simgear/io/untar.cxx | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/simgear/io/test_untar.cxx b/simgear/io/test_untar.cxx index 153519f0..92c4ce29 100644 --- a/simgear/io/test_untar.cxx +++ b/simgear/io/test_untar.cxx @@ -33,6 +33,7 @@ void testTarGz() SG_VERIFY(TarExtractor::isTarData(buf, bufSize)); + f.close(); } void testPlainTar() @@ -48,12 +49,13 @@ void testPlainTar() SG_VERIFY(TarExtractor::isTarData(buf, bufSize)); + f.close(); } -int main (int ac, char ** av) +int main(int ac, char ** av) { testTarGz(); testPlainTar(); - return 0; + return 0; } diff --git a/simgear/io/untar.cxx b/simgear/io/untar.cxx index 0eeab2f8..e6c8a2e8 100644 --- a/simgear/io/untar.cxx +++ b/simgear/io/untar.cxx @@ -403,22 +403,26 @@ bool TarExtractor::isTarData(const uint8_t* bytes, size_t count) z.avail_in = count; if (inflateInit2(&z, ZLIB_INFLATE_WINDOW_BITS | ZLIB_DECODE_GZIP_HEADER) != Z_OK) { + inflateEnd(&z); return false; } int result = inflate(&z, Z_SYNC_FLUSH); if (result != Z_OK) { SG_LOG(SG_IO, SG_WARN, "inflate failed:" << result); + inflateEnd(&z); return false; // not tar data } size_t written = 4096 - z.avail_out; if (written < TAR_HEADER_BLOCK_SIZE) { SG_LOG(SG_IO, SG_WARN, "insufficient data for header"); + inflateEnd(&z); return false; } header = reinterpret_cast(zlibOutput); + inflateEnd(&z); } else { // uncompressed tar if (count < TAR_HEADER_BLOCK_SIZE) { From 53e6bec425c6ae442d9b9421605c4d667e9d1114 Mon Sep 17 00:00:00 2001 From: xDraconian Date: Sun, 17 Dec 2017 10:06:20 +0100 Subject: [PATCH 18/18] Tests: resolve several memory leaks --- simgear/scene/util/parse_color_test.cxx | 4 ++-- simgear/structure/expression_test.cxx | 6 +++--- simgear/structure/state_machine_test.cxx | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/simgear/scene/util/parse_color_test.cxx b/simgear/scene/util/parse_color_test.cxx index 0e6fcdd0..0db7f12c 100644 --- a/simgear/scene/util/parse_color_test.cxx +++ b/simgear/scene/util/parse_color_test.cxx @@ -7,7 +7,7 @@ #include #include - +#include #define VERIFY_COLOR(str, r, g, b, a) \ SG_VERIFY(simgear::parseColor(str, color)) \ @@ -28,7 +28,7 @@ int main (int ac, char ** av) SGPropertyNode color_node, color_arg; color_arg.setStringValue("#000000"); - simgear::PropertyInterpolator* interp = new simgear::ColorInterpolator; + auto interp = std::unique_ptr(new simgear::ColorInterpolator); interp->reset(color_arg); interp->update(color_node, 0.5); // with no color it should immediately set to the target diff --git a/simgear/structure/expression_test.cxx b/simgear/structure/expression_test.cxx index 0ee10154..178e47d9 100644 --- a/simgear/structure/expression_test.cxx +++ b/simgear/structure/expression_test.cxx @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -81,8 +82,8 @@ void testParse() "" ""; - SGPropertyNode* desc = new SGPropertyNode; - readProperties(xml2, strlen(xml2), desc); + auto desc = std::unique_ptr(new SGPropertyNode); + readProperties(xml2, strlen(xml2), desc.get()); SGSharedPtr expr = SGReadDoubleExpression(propertyTree, desc->getChild(0)); @@ -107,4 +108,3 @@ int main(int argc, char* argv[]) cout << __FILE__ << ": All tests passed" << endl; return EXIT_SUCCESS; } - diff --git a/simgear/structure/state_machine_test.cxx b/simgear/structure/state_machine_test.cxx index 558c72b8..167c3b0a 100644 --- a/simgear/structure/state_machine_test.cxx +++ b/simgear/structure/state_machine_test.cxx @@ -14,6 +14,7 @@ #include #include #include +#include #include "StateMachine.hxx" @@ -230,11 +231,11 @@ void testParse() )"; - SGPropertyNode* desc = new SGPropertyNode; - readProperties(xml, strlen(xml), desc); + auto desc = std::unique_ptr(new SGPropertyNode); + readProperties(xml, strlen(xml), desc.get()); SGPropertyNode_ptr root(new SGPropertyNode); - StateMachine_ptr sm = StateMachine::createFromPlist(desc, root); + StateMachine_ptr sm = StateMachine::createFromPlist(desc.get(), root); SG_VERIFY(sm->findStateByName("one") != NULL); SG_VERIFY(sm->findStateByName("two") != NULL); @@ -250,4 +251,3 @@ int main(int argc, char* argv[]) cout << __FILE__ << ": All tests passed" << endl; return EXIT_SUCCESS; } -