From b26e1531811a9ebfe43761e6c0bb921435de8228 Mon Sep 17 00:00:00 2001 From: "J. Daniel Smith" Date: Mon, 2 Oct 2023 11:23:57 -0400 Subject: [PATCH] latest from CODA-OSS (#583) * latest from CODA-OSS * CRLF * Squashed 'externals/coda-oss/' changes from e87c32b4de..5b892bf5f7 5b892bf5f7 release 2023-08-18 (#723) 0b1327d1e6 restore mem::AutoPtr; too much of a hassle moving it to numpyutils :-( (#722) 7691adb566 normalize line endings (#721) b7d50efdd9 update to HDF5 1.14.2 (#720) fcc96ec699 Update .gitattributes (#719) bb82a94c9e xerces-c 3.2.4 (#718) ef4ad7cf39 Update to e2fsprogs 1.47.0 (#717) b4ca18a114 fix compiler warning about order of operations a5df5b823d update to HighFive 2.7.1 (#716) 4109ee5d20 `mem::AutoPtr` is only for Python bindings (#715) 00d843f873 remove hdf5.lite (#714) 443dd38255 Reduce compiler warnings, speed up builds (#713) d60861821d get optional working with partial C++17 (#712) d5bd0d8045 "warning STL4036: is removed in C++20." c19ece7f90 Don't interfere with a partial C++20 implementation (#711) 065e86ddcb operator==() for QName (#710) 1c16380ced remove zint* typedefs; don't want to encourage use of types::Complex (#709) 6dd2479918 our optional<> is now closer to C++17 (#708) 87ac617396 strict checking on `std::complex` is too much of a hassle for now 034d52c863 overloads to byte-swap type::Complex are too much trouble (#707) 42d449c334 sys::byteSwap overloads for types::Complex (#705) 4092fd8e76 remove work-around for NITRO bug (#704) e2472acfc1 build in NITRO and SIX (#703) 32ccf91052 Use same build paths as Visual Studio (#701) 366ac9f43f Another round of removing compiler warnings (#702) a7f8ef2605 Fix compile warnings from building CODA (#700) f70b4202f1 account for coda-oss.vcxproj being in other SLNs af3faebfc6 Remove more compiler/code-analysis warnings (#699) 82be2a6db2 unittests should work w/o install (#698) dbb90a06d9 add msbuild for coda-oss.sln (#697) 5a417140a6 reduce compiler warnings (#696) 288619dfa3 all modules now part of coda-oss.vcxproj (#695) c2fc5fc660 add more projects to coda-oss-lite.vcxproj (#694) ceb86c186e support $(PlatformToolset) as a "special" environment variable (#693) d78a8595a7 OS::getSIMDInstructionSet() utility (#692) 2d2df467da fix `python3 waf dumplib` 54033e70e3 Merge branch 'main' into feature/complex_short 3c63f9f65e std::numbers from C++20 (#691) 892dd0e00f ComplexInteger and ComplexReal to better match existing naming conventions (#690) b3872181ec match coda-oss naming conventions (#688) 704d6867f9 beef-up our complex type (#687) 47c1c1cd66 check is_absolute() for URLs (#686) c042373e16 be sure our Path::isAbolute() matches std::filesystem::path::absolute() (#684) ad10286bc0 volatile is about "special" memory, not threading (#685) f4d42005fa fix build error in NITRO ff11a5557e keep using std::complex for now (#682) c88b9c0532 types::complex (#681) d1244a0804 don't need our own make_unique in C++14 (#680) aeec0131c5 assert()s for mem::CopyablePtr (#679) 72b0ebd603 add types::complex_short (#678) 932130a580 patch to build other projects c00c1f203d coda-oss release 2023-06-06 (#677) ef54bbcd53 remove more compiler warnings (#676) dadfc5ce62 distinguish between byte-swapping a buffer and single value (#674) 90187f6cd8 more xml.lite tweaks for SIDD-3.0/ISM (#675) eb99607720 stronger type-checking for byteSwap() (#673) ff4f820ed8 xml.lite tweaks to support SIDD 3.0 ISM (#672) b1de8c0e5e std::byte should be a unique type (#671) c05bf9a028 allow enums to be byte-swapped too 1f9fd88d6d remove spurious 47684c45b8 byteSwap now uses byte buffers (#670) cbc659db27 add swapBytes() utility from SIX (#669) 891481b64f simplify byte-swapping (#668) 540ae763e5 more byteSwap() tweaks 0774c03c46 threaded byteSwap() (#667) d156370d36 swapping a single-byte value makes no sense c120e3255d be sure parameter is used to avoid compiler warning e85ec93317 --output-on-failure for CTest (#666) e80376197b turn off "there is no warning number" warning c5f0a5d154 A C-string may not be NULL-terminated (#665) 0c5eb29ae7 use platform-specific routines for byteSwap() (#664) 0b7d581fa6 remove transform_async() (#663) f6489b6bef Merge branch 'main' into feature/xml.lite_tweaks 836c426a2b use function-pointers so that isConsoleOutput is only checked once 56e3c45b1b move depthPrint() functionality into non-member function in preparation for future changes ddcd26d972 Merge branch 'main' into feature/xml.lite_tweaks 69cc0e5063 use the more rigorous create_and_check_datatype() 9efb875584 Merge branch 'main' into feature/hdf5 4d2f2f4173 more HighFive unittests (#662) 14191a844a HighFive::create_datatype() goes from C++ to HighFive 98583473fb utility routines to read string attributes 1fa75ce81e use the C API to read a string attribute 71e7b69f54 still can't figure out how to read a string attribute :-( e96f37a69b test reading the file attributes a25244519c getAttribute() unittest 8f12a3000b getDataType() unittest 857ff0af32 HighFive utility routines (#661) 1d687db57b writeDataSet() utility overload 106aa68945 sigh ... H5Easy::dump() fill fails on Windows/WAF :-( 2641b60b2b Merge branch 'main' into feature/hdf5 35c19e7e81 change actions to @v3 (#660) 212bbd3a36 works on local machine, but not build server ... ? 7125118b09 dump of 1D vector doesn't work :-( c704db4352 sigh ... WAF build still failing :-( 01aae46163 does dump() of a 1D vector work? 76a53c8134 comment-out H5 writing :-( 0f0e19affe test_highfive_dump() cb8f737957 trying to get highfive_dump() unittest working w/Windows-WAF 6584a264af does test_highfive_create() work? cde6147ced tweak HighFive wrappers (#659) 3165668545 Revert "trying HighFive "write" unittests again" a9ec24ca4d trying HighFive "write" unittests again 585ad49a56 tweak names of utility routines 4c91a4d97a make it easier to read a std::vector and std::vecotr 0217ffa26c readDataSet() now works for 1D data 95e8973f29 trying to get hdf5::lite::load() working 4d294611d4 "const" correctness 5e6305c3f7 fix load_complex() 4a134dc5f1 start work on utility routines to read complex data from HDF5 9d76a7f41e Merge branch 'main' into feature/hdf5 8f9667a240 whitepsace ebd3fc99ea Merge branch 'main' into feature/hdf5 40091b069c comment-out writing tests for now ... need to figure our WAF bulid failure 935aa34592 be sure the dataset has real data 114b9bf33c update release notes bd9c0b26c5 tweak HighFive utility routines acda1ef577 turn off diagnostics around expected failures 22a7488402 readDataSet() utility routine for HighFive bd88a8c256 HighFive writeDataSet() utility to work with our SpanRC 6142f5b339 use HighFive routines to write a HDF5 file 5bbf1abaff Use HiveFive routines to get info about the file 84fbc83789 duplicate unittests with H5Easy f1f054c03a Merge branch 'main' into feature/hdf5 9b63ca470c fix directory names f6f826689a fix directory names 7aeb82c336 Merge branch 'main' into feature/hdf5 d028baaebd hook up HighFive header-only library (#653) 3083b0a313 Revert "HighFive 2.6.2" 246985a7f0 Revert ""build" HighFive HDF5 library" a8b75a5865 Revert "turn off HighFive Boost support" ec68d5f830 Revert "Add HighFive unittests" f1f85b9e7f Revert "get test_high_five_base more-or-less compiling" 5ea634ee15 Revert "more work on getting HighFive unittests to build" ecc45433c7 more work on getting HighFive unittests to build bb194788ab get test_high_five_base more-or-less compiling d42bde0004 Add HighFive unittests ddc86bb328 turn off HighFive Boost support b255122d4f "build" HighFive HDF5 library 396cc3ef2a HighFive 2.6.2 5e5f9d9c0f Merge branch 'main' into feature/hdf5 ee938b4a52 changes from SIX bb764df90b Merge branch 'main' into feature/xml.lite_tweaks de2a243800 make derived classes 'final' if possible 14e19bcd21 Change xml lite function to virtual (#645) 8f42ac8e9e Merge branch 'main' into feature/xml.lite_tweaks 18ad90645f hdf5Write unittest 3462e11792 createFile() and writeFile() overloads ecee81d532 fix typos 197eecfa62 sketch-out hdf5::lite::writeFile() bd2311795e use SpanRC for writeFile(), not yet implemented ea9af75109 simple SpanRC to hold a 2D-size and pointer 027c19ee8a createFile() unittest 1f9d07ecbc hook up createFile() 8c7e4473f0 start hooking up HDF5 writing 146e0bea3b Merge branch 'main' into feature/hdf5 88ca9fcb7f Merge branch 'main' into feature/hdf5 42b604b463 Squashed commit of the following: 10ee602c25 Merge branch 'main' into feature/hdf5 67aa42b69d restore changes from "main" 8bbfcbfbfe unittests can be simplified to match fewer "view" classes 126bb802ea Merge branch 'main' into feature/hdf5 3f8ba7a423 again, don't need a class just to convert from std::vector<> to std::span<> 24c2b489c8 Squashed commit of the following: 2703c119d4 Squashed commit of the following: 9d5228a2be don't need an entire class just to convert a std::vector<> into std::span<> 51bc931dcd Merge branch 'main' into feature/hdf5 a84f258160 Squashed commit of the following: c4d2ed696e add missing #include guards, fix type in existing #include guard d541525a01 use a single ComplexViewConstIterator for all views 86e6a459fe CODA_OSS_disable_warning causes GCC errors :-( 5d4b9c2cb6 only need an custom iterator for ComplexSpansView d9f0fb1286 hook up iterators b9329e4db0 initial pass at a ComplexViewConstIterator 6352388739 remove compiler warning about unused "constexpr" variables b39f6096fb use the casing from H5 to make copy/pasting code slightly easier 0887b13eb4 Merge branch 'main' into feature/hdf5 bd07df1cae Consistent casing for Dataset, Datatype, Dataspace 7acd30ee23 tweak hdf5.lite dependencies 38ab914dfd Jupyter notebook for creating H5 files 95a040e0bf _small.h5 is now (correctly) FLOAT32 107e7c4876 make a simple values() member function to avoid template magic e1feca9194 use TEST_SPECIFIC_EXCEPTION macro instead of try/catch 7383336888 readDatasetT() now throws for the wrong buffer type 6b2cc25294 Merge branch 'feature/hdf5' of github.com:mdaus/coda-oss into feature/hdf5 310f8fd3d5 can't get template magic right for copy_axis() 86b306d596 stepping through copy ctors in the debugger is annoying f243e92d68 trying to make wrong type of buffer fail 2b10d96529 read in new sample file a28e59d8c5 help the compiler with type deduction 49bf5e9bc2 nested_complex_float_data_small.h5 e029325fc0 utility routines to "deconstruct" and array of std::complex dede3bd393 Merge branch 'main' into feature/hdf5 904b1ef5ec tweak class names, make_() and copy() utility routines 8237b9efbf make it harder to pass the wrong types to ComplexViews 4d9aeda2cd ComplexArrayView and ComplexParallelView utility classes f5e367dfa6 test std::span> a4a2844f26 read in the nested "i" and "r" data 1156152650 sample file has subgroups 8e1b7869aa Merge branch 'feature/hdf5' of github.com:mdaus/coda-oss into feature/hdf5 9f4232a1dd update sample H5 file 8c55db73ae walk through HDF5 sub-groups 7775ed9c43 Update 123_barfoo_catdog_cx.h5 677975d7ca Matlab code to create sample H5 file a0e7dfe07b Update test_hdf5info.cpp 0b67e1602f pass __FILE__ and __LINE__ from calling site for a more accurate exception message 86a6773213 skeleton for more sample data 85f79b0999 Merge branch 'main' into feature/hdf5 18088e9421 Merge branch 'main' into feature/hdf5 3a1d17692f Merge branch 'main' into feature/hdf5 1755c69d70 Merge branch 'main' into feature/hdf5 9ad015432d No more "11" suffix on exception names c20d962511 Squashed commit of the following: c88cee999b other values to be filled-in bca4a4ecd8 incorporation NamedObject from HDF5 docs 61fa68f72e groupInfo() 460e7d7665 datasetInfo() 14eb9b764b start filling in DatasetInfo afe5f1c3a0 start to fill in DatasetInfo 77a968c72d start filling in GroupInfo d81bcdfd92 openGroup() to open groups (loc) a0cd294697 comment-out "dataset" unittest for now 86e0060245 begin filling in FileInfo 366dda6ab6 a return_type_of utility is needed to deduce the return type e219282638 explicitly pass return type to template 4937ccd11d template to reduce boilerplate when calling try_catch_H5Exceptions b3b5ebde78 use new exception utility routines ea1c03ef0c put exception handling/conversion in a utility routine 819a99d397 utility routine for exception handling 6f34eea979 put utilities in a separate file for easier reuse fcbde4f241 break utility routines into smaller pieces for easier reuse 52358ea8a9 WIN32 no longer automatically defined? 5a42864722 Revert "build HDF5 with C89" 680e599e9d build HDF5 with C89 a87a071218 Merge branch 'main' into feature/hdf5 8447c1a900 Revert "sym-links instead of copying files" db3b5e12b4 Merge branch 'main' into feature/xml.lite_tweaks fb60b5696f Merge branch 'main' into feature/hdf5 5110a5cc81 Comments about _u and _q 1a937d32cf Merge branch 'main' into feature/xml.lite_tweaks fa06f04d7e get ready for hdf5.lite enhancdements b040c7c437 sym-links instead of copying files aa431bb477 use _u for xml::lite::Uri 3d0c6d58ce fix case-sensitive #include filename 93dcd0e527 operator() for getElementByName() 75a93af859 more operator[] overloads to make attribute management easier 4ab8216f87 user-defined string literals to remove some noise around xml::lite::QName f82f0b0fc6 Merge branch 'main' into feature/xml.lite_tweaks ae30e36443 Merge branch 'feature/xml.lite_tweaks' of github.com:mdaus/coda-oss into feature/xml.lite_tweaks ffdd9beb0b simplify attribute creation 9bf5414f5d simplify attribute creation 82d7a4e959 SWIG gets confused about namespaces 7a61d0741f fix bug on Element ctor uncovered by unittest fdd7e58c1a QName is also in the xerces namespace which confuses SWIG bindings a325b7053b operator+=() overload for addChild daf30e6c0e Merge branch 'feature/xml.lite_tweaks' of github.com:mdaus/coda-oss into feature/xml.lite_tweaks b887d2b476 provide overloads for Element& rather than creating new "reference" types 1fa6bba388 rename test_xmleasy.cpp 7c8c9e0f1c += overload 850da6f63d overload for std::string 4547fc5a75 use UIT-8 strings for characterData 4723462a3b convenient addChild() overloads e48720753a copy over ElementReference from xml.easy a4ca30a0d6 Merge branch 'main' into feature/xml.lite_tweaks 6ae9f0b715 Revert "check-in of new xml.easy (to move code between computers)" f7466a6d75 Revert "simple routines for single element" a5490230d6 Revert "make some operators simplier ways of calling functions" c9a25630a6 Revert "get document creation working" 8af8710b05 Revert "free functions instead of member functions" 16c3847cb2 Revert "ElementReference distinct from Element" 7d68e156ff Revert "ElementMutableReference" 00eb2a2826 Merge branch 'main' into feature/xml.lite_tweaks a42969c1f4 ElementMutableReference a20ae9355e ElementReference distinct from Element 14eeeea0b5 free functions instead of member functions 4aae014b39 get document creation working 8835692699 make some operators simplier ways of calling functions 053bd1212a simple routines for single element 8bf701a2ea check-in of new xml.easy (to move code between computers) 41f959051c unittests for creating XML documents from scratch 9752d50ae2 Merge branch 'main' into feature/xml.lite_tweaks 1531d57095 by default, don't validate strings passed to Uri() 46d13d4bf7 Merge branch 'master' into feature/xml.lite_tweaks 39b547d321 remove more vestiges of Expat and LibXML ec8274d524 remove LibXML and Expat as they're no longer used/supported. 20eeefeef6 Merge branch 'master' into feature/xml.lite_tweaks 95074b9b1a update for newer Intel compiler 7024f71e1b Merge branch 'master' into feature/xml.lite_tweaks 57b1cbc83d Merge branch 'master' into feature/xml.lite_tweaks 4b67561c3d remove validate() overload that nobody is using fa15f1e5dc Squashed commit of the following: 1484a90909 test the new validate() API 470da70fb8 hookup StringStreamT routines 2cddf25047 begin hooking up validate() overloads 1b5d910f38 overload validate() for UTF-8 and Windows-1252 03309b8c9f Squashed commit of the following: b72c6c5bf2 older compiler doesn't like our make_unique af8f00307f validate UTF-8 XML on Linux 211188613e unit-test for LEGACY XML validation 3c1169d2b5 Squashed commit of the following: 3afff19cad std::filesystem::path for FileInputStreamOS 908d452f8f WIP: validate all of our sample XML files 00f9bb16bc validate against a XML schema 243d8c356c Merge branch 'master' into feature/xml.lite_tweaks 2815d707d9 fix to work with SWIG bindings. :-( 4608621326 trying (again) to remove vestiages of old code e3c83a8587 Revert "new code should use UTF-8" 811207c920 new code should use UTF-8 0ffd835f96 Squashed commit of the following: 1e7e03ded0 Merge branch 'master' into feature/xml.lite_tweaks c1d806affa Merge branch 'master' into feature/xml.lite_tweaks 850d3c811d str::strip() that can be easier to use than str::trim() 580ba9c8c3 explicitly =delete move 2b39831a80 Squashed commit of the following: 39eebdc23f Merge branch 'master' into feature/xml.lite_tweaks 9adf86cbaf force calling new UTF-8 write() routines ea61b62045 Merge branch 'master' into feature/xml.lite_tweaks 8a34583fa0 overload to take schemaPaths as filesystem::path 8671b442f7 parse XML embedded in a binary file ec4a902f14 updates from xerces.lite 80dc4d9635 updates from xerces.lite 549766d6c1 Attributes::contains() no longer catches an exception 8a645ceac3 need "sys/" when building in other environments 36af082690 super-simple URI validation 78ef28a3e2 SWIG bindings are a PITA! :-( e9cba8491e SWIG needs help with Uri 8a8d8dc072 another routines used by pre-build SWIG bindings 818e1ec5d3 pre-build SWIG bindings use getElementByTagName() member function 067cac5d85 old compiler gets confused on unadorned QName ba92c0ae7e more use of Uri and QName 446c7d17a7 use QName in new code d6f8b0c836 more direct use of QName 90fff1c737 use xml::lite::QName instead of tuple 646cbb5ed4 more direct use of QName and Uri ba589ea3b3 make QName more robust bab0ee8b5e createElement() -> addNewElement() e3a145747a grab changes from six-library 32285e95c4 Merge branch 'master' into feature/xml.lite_tweaks 9f79f0bf62 Merge branch 'master' into feature/xml.lite_tweaks a12bbc32c6 make it easier to create new Elements with a value fc9967f986 make it easy for callers to addChild() keep a reference to the Element 4627766b7d be sure test_xmlparser works in "externals" of other projects bf22763961 "private" is part of the name-mangling fad92bcc8f making sure copy-ctor is implemented f90fdcead0 consolidate common XML test code 9fc53f2d51 use str:: utility for casting 6da6f794bb still trying to find the right macro for SWIG 0c1b86c566 still trying to fix SWIG fdc6fc9bd6 trying to fix SWIG build error 7835e8c270 SWIG needs copy-ctor 585695942d disable copy/assignment for Element, it's probably almost always wrong 391fed6135 fix double-delete caused by copying 61790fe695 retry parsing XML with Windows-1252 if first parse() fails 63cffac59e change string_encoding to match coda-oss style of PascalCase 010479bbec read an XML file we know is wrongly encoded as Windows-1252 9a05050621 more references instead of pointers 2d44b69519 Reading Windows-1252 w/o "encoding" fails 63dc7b0762 read Windows-1252 too c9434c9cbe test as UIT-8 too f310ccf0cf get reading from UTF-8 XML working on Windows 1fa39c2be0 get testReadUtf8XmlFile working on Linux 1a83cd8157 sys::Path is too much trouble right now ed60aa22c9 unit-test to read XML from a file a9336db7c6 Squashed commit of the following: 0825beb0d3 Merge branch 'master' into feature/xml.lite_tweaks c618489be7 Merge branch 'master' into feature/xml.lite_tweaks e8e4b8fe1d determine string_encoding based on platform 1f43bcfc26 create a new Element by using the platform to determine "characterData" encoding 961bef66b4 Merge branch 'master' into feature/xml.lite_tweaks e9798a5cba fix static_assert() 6f77728748 Merge branch 'master' into feature/xml.lite_tweaks b98d4f5a91 Merge branch 'master' into feature/xml.lite_tweaks 1b5abba2a6 The (old) version of SWIG we're using doesn't like certain C++11 features. 53bdeabaf7 Merge branch 'master' into feature/xml.lite_tweaks 60cf8ae80f "" doesn't work with decltype() in older C++ 97e72477a5 reduce getValue() overloads by making "key" a template argument 5e6373e557 reduce code duplication f9e7cfeee5 provide castValue instead of getValue(T&) cbd0bd8f24 castValue throws instead of returning a bool like getValue(T&) 87c7514fce Merge branch 'master' into feature/xml.lite_tweaks 10cc61223a make getElement*() consistent for zero or >1 results f5b137e3cd Merge branch 'master' into feature/xml.lite_tweaks 1765efc622 allow clients to specify toType() and toString() for getValue() and setValue() df8b746e12 allow clients to specify their own toType/toString routines 66702726ad Merge branch 'master' into feature/xml.lite_tweaks 6956311f14 Merge branch 'master' into feature/xml.lite_tweaks d505f3593a Merge branch 'master' into feature/xml.lite_tweaks fbd106115f catch a BadCastException and return false from getValue() 3a78377b55 use a template to reduce duplicated code 0ad4b86062 Merge branch 'master' into feature/xml.lite_tweaks a848aa3a20 get & set the characer data as a type f3ee1ee12a utility routines to set an attribute value 5952276839 templates to get an attribute value convert to a specific type 06639227b3 miised a change in last commit 1aa458ef8b add getValue() overloads that return true/false rather than throwing faa6d30752 added getElementByTagName() overloads as that's a very common use-case git-subtree-dir: externals/coda-oss git-subtree-split: 5b892bf5f7b99a50b53e47c8b9f9f736940ab939 * latest from CODA-OSS * CODA-OSS removed EncodedStringView.h * str::format changes from CODA-OSS * str::format changes from CODA-OSS * latest from CODA-OSS * latest from CODA-OSS * suppress new compiler warning * Squashed 'externals/coda-oss/' changes from 5b892bf5f7..bf7ae4a718 bf7ae4a718 use overloads rather than varargs for std::format() (#727) 22e0502076 utility routines to reduce duplicated code (#726) a5ea606471 remove str::EncodedStringView (#725) 168cbae01b reduce differences between 'main' and 'cpp17' (#724) git-subtree-dir: externals/coda-oss git-subtree-split: bf7ae4a718bd97a55ed37d2dd0a514deebc97776 * toString() changes from CODA-OSS * str::format() changes from CODA-OSS * str::format() changes from CODA-OSS * more FmtX() overloads * Squashed 'externals/coda-oss/' changes from 8dee6f7a68..165a799c54 165a799c54 more FmtX() overloads (#729) git-subtree-dir: externals/coda-oss git-subtree-split: 165a799c5413e736f659e3f4c9d8d0a031ac5517 * another FmtX() overload * latest from CODA-OSS * Squashed 'externals/coda-oss/' changes from 165a799c54..ac8c312db5 ac8c312db5 Only allow va_args formatting under controlled circumstances (#735) 589aacfd7a str::to_native() for when conversion to std::string really is needed 743feb41e0 try hard not to lose string encoding (#734) 1854a9b46f hide use of str::cast() inside `details` namespace (#733) fbe0c85f9b compile-time getSIMDInstructionSet() (#732) ee2c46358d more consistent naming for routines to convert between encodings (#731) 00e2dd9286 another FmtX() overload git-subtree-dir: externals/coda-oss git-subtree-split: ac8c312db5a63e1eaf75300bb31708396a1fe79d * account for str::Format() changes * latest from CODA-OSS * Squashed 'externals/coda-oss/' changes from ac8c312db5..333b910247 333b910247 Squashed commit of the following: git-subtree-dir: externals/coda-oss git-subtree-split: 333b9102479d3d2c7d41425dbcfa41a7eabf7b1d * copy externals * Squashed 'externals/coda-oss/' changes from c92a55d7c7..95ff879bab 95ff879bab make it easier to turn on AVX2/AVX512F (#740) a950c848be enable AVX2 and AVX512F CMake builds (#739) 3697370855 use std::ssize() to reduce casts (#738) 8ae7dabace std::size() and std::ssize() (#737) 8db480be5b enable ASAN for GitHub builds (#736) git-subtree-dir: externals/coda-oss git-subtree-split: 95ff879babba421c57ece442c3324c98d68fdbc7 * latest from CODA-OSS --- .../.github/workflows/build_unittest.yml | 10 ++-- externals/coda-oss/CMakeLists.txt | 11 ---- externals/coda-oss/cmake/CodaBuild.cmake | 37 ++++++++++++++ .../modules/c++/avx/unittests/test_m256.cpp | 44 ++++++++++++++++ .../modules/c++/cli/source/ArgumentParser.cpp | 4 +- .../modules/c++/cli/unittests/test_cli.cpp | 7 +-- .../c++/coda_oss/include/coda_oss/span.h | 28 +++++++++++ .../modules/c++/io/include/io/ByteStream.h | 9 ++-- .../modules/c++/io/source/ByteStream.cpp | 12 +++-- .../modules/c++/io/unittests/test_streams.cpp | 4 +- .../unittests/test_exception_logger.cpp | 3 +- .../c++/math.linear/unittests/test_Vector.cpp | 11 ++-- .../include/sio/lite/UserDataDictionary.h | 1 + .../c++/sio.lite/source/FileHeader.cpp | 6 +-- .../coda-oss/modules/c++/std/include/std/span | 47 ++++++++++++++++++ .../modules/c++/str/unittests/test_str.cpp | 5 +- .../c++/sys/unittests/test_NaN_testing.cpp | 36 +++++++++++++- .../xml.lite/unittests/test_xmlelement.cpp | 9 ++-- .../c++/xml.lite/unittests/test_xmlparser.cpp | 7 +-- .../modules/c++/zip/include/zip/ZipFile.h | 6 ++- .../modules/drivers/uuid/CMakeLists.txt | 2 +- .../modules/drivers/uuid/e2fsprogs-1.47.0.tar | Bin 7956480 -> 7956480 bytes 22 files changed, 247 insertions(+), 52 deletions(-) diff --git a/externals/coda-oss/.github/workflows/build_unittest.yml b/externals/coda-oss/.github/workflows/build_unittest.yml index 5f8044cb5..8b6a5dd22 100644 --- a/externals/coda-oss/.github/workflows/build_unittest.yml +++ b/externals/coda-oss/.github/workflows/build_unittest.yml @@ -58,7 +58,8 @@ jobs: os: [windows-latest] platform: [x64] configuration: [Debug] # Debug turns on more compiler warnings - name: ${{ matrix.os }}-msbuild + avx: [AVX2, AVX512F] + name: ${{ matrix.os }}-${{ matrix.avx }}-msbuild runs-on: ${{ matrix.os }} steps: @@ -68,7 +69,7 @@ jobs: ls env: mkdir out cd out - cmake .. -DCMAKE_INSTALL_PREFIX=install\${{ matrix.platform }}-${{ matrix.configuration }} -DENABLE_PYTHON=OFF + cmake .. -DCMAKE_INSTALL_PREFIX=install\${{ matrix.platform }}-${{ matrix.configuration }} -DENABLE_PYTHON=OFF -DENABLE_${{ matrix.avx }}=ON - name: build run: | cd out @@ -131,14 +132,15 @@ jobs: matrix: os: [ubuntu-latest] configuration: [Debug, Release] - name: ${{ matrix.os }}-${{ matrix.configuration }}-CMake + avx: [AVX2, AVX512F] + name: ${{ matrix.os }}-${{ matrix.configuration }}-${{ matrix.avx }}-CMake runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 - name: configure run: | mkdir out && cd out - cmake .. -DENABLE_PYTHON=OFF -DENABLE_ASAN=ON + cmake .. -DENABLE_PYTHON=OFF -DENABLE_ASAN=ON -DENABLE_${{ matrix.avx }}=ON - name: build run: | cd out diff --git a/externals/coda-oss/CMakeLists.txt b/externals/coda-oss/CMakeLists.txt index 4b1bc2c64..f512d520a 100644 --- a/externals/coda-oss/CMakeLists.txt +++ b/externals/coda-oss/CMakeLists.txt @@ -24,19 +24,8 @@ if (${CMAKE_PROJECT_NAME} STREQUAL coda-oss) if (MSVC) add_compile_options(/WX) # warnings as errors add_compile_options(/MP) # multi-processor compile - - if (ENABLE_ASAN) - # https://docs.microsoft.com/en-us/cpp/sanitizers/asan?view=msvc-160 - add_compile_options(/fsanitize=address) - endif() elseif (UNIX) add_compile_options(-Werror) # warnings as errors - - if (ENABLE_ASAN) - # https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html - add_compile_options(-fsanitize=address) - add_link_options(-fsanitize=address) - endif() endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") diff --git a/externals/coda-oss/cmake/CodaBuild.cmake b/externals/coda-oss/cmake/CodaBuild.cmake index 69a143c1b..142773788 100644 --- a/externals/coda-oss/cmake/CodaBuild.cmake +++ b/externals/coda-oss/cmake/CodaBuild.cmake @@ -165,6 +165,22 @@ macro(coda_initialize_build) # This should probably be replaced by GenerateExportHeader #set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD TRUE) + + if (ENABLE_ASAN) + # https://docs.microsoft.com/en-us/cpp/sanitizers/asan?view=msvc-160 + add_compile_options(/fsanitize=address) + endif() + + # Note SSE2 is implicitly enabled for x64 builds. + if (ENABLE_AVX2 AND (NOT ENABLE_AVX512F)) + # https://learn.microsoft.com/en-us/cpp/build/reference/arch-x86?view=msvc-170 + add_compile_options(/arch:AVX2) + endif() + if (ENABLE_AVX512F) + # https://learn.microsoft.com/en-us/cpp/build/reference/arch-x86?view=msvc-170 + add_compile_options(/arch:AVX512) + endif() + endif() # Unix/Linux specific options @@ -173,6 +189,27 @@ macro(coda_initialize_build) -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 ) + + if (ENABLE_ASAN) + # https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html + add_compile_options(-fsanitize=address) + add_link_options(-fsanitize=address) + endif() + + # Note SSE2 is implicitly enabled for x64 builds. + if (ENABLE_AVX2 AND (NOT ENABLE_AVX512F)) + # https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html + # It doesn't look like GCC has a specific option for AVX2; + # other projects use "haswell" + add_compile_options(-march=haswell) + endif() + if (ENABLE_AVX512F) + # https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html + # It doesn't look like GCC has a specific option for AVX512F; + # other projects use "native" which isn't quite correct.' + add_compile_options(-march=native) + endif() + endif() # all targets should be installed using this export set diff --git a/externals/coda-oss/modules/c++/avx/unittests/test_m256.cpp b/externals/coda-oss/modules/c++/avx/unittests/test_m256.cpp index 8c6cdc47b..920a0f9f8 100644 --- a/externals/coda-oss/modules/c++/avx/unittests/test_m256.cpp +++ b/externals/coda-oss/modules/c++/avx/unittests/test_m256.cpp @@ -25,7 +25,9 @@ #include #include +#include #include +#include TEST_CASE(extractf) { @@ -49,8 +51,50 @@ TEST_CASE(extractf) */ TEST_SUCCESS; } + +TEST_CASE(test_getSIMDInstructionSet) +{ + // This is the reverse of getSIMDInstructionSet(): it uses the macros to generate a value. + constexpr auto simdInstructionSet = sys::getSIMDInstructionSet(); + #if __AVX512F__ + static_assert(simdInstructionSet == sys::SIMDInstructionSet::AVX512F, "getSIMDInstructionSet()"); + #elif __AVX2__ + static_assert(simdInstructionSet == sys::SIMDInstructionSet::AVX2, "getSIMDInstructionSet()"); + #else + static_assert(simdInstructionSet == sys::SIMDInstructionSet::SSE2, "getSIMDInstructionSet()"); + #endif + CODA_OSS_disable_warning_push + #if _MSC_VER + #pragma warning(disable: 4127) // conditional expression is constant + #endif + + switch (sys::getSIMDInstructionSet()) // run-time value + { + case sys::SIMDInstructionSet::SSE2: + { + TEST_ASSERT(simdInstructionSet == sys::SIMDInstructionSet::SSE2); + break; + } + case sys::SIMDInstructionSet::AVX2: + { + TEST_ASSERT(simdInstructionSet == sys::SIMDInstructionSet::AVX2); + break; + } + case sys::SIMDInstructionSet::AVX512F: + { + TEST_ASSERT(simdInstructionSet == sys::SIMDInstructionSet::AVX512F); + break; + } + default: + { + TEST_FAIL; + } + } + CODA_OSS_disable_warning_pop +} TEST_MAIN( TEST_CHECK(extractf); + TEST_CHECK(test_getSIMDInstructionSet); ) diff --git a/externals/coda-oss/modules/c++/cli/source/ArgumentParser.cpp b/externals/coda-oss/modules/c++/cli/source/ArgumentParser.cpp index 3694e7ed3..e7763e4aa 100644 --- a/externals/coda-oss/modules/c++/cli/source/ArgumentParser.cpp +++ b/externals/coda-oss/modules/c++/cli/source/ArgumentParser.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -533,8 +534,7 @@ std::unique_ptr cli::ArgumentParser::parse(const std::string& prog break; } } - if (maxArgs >= 0 && - v->size() >= static_cast(maxArgs)) + if (maxArgs >= 0 && std::ssize(*v) >= maxArgs) { // it's another positional argument, so we break out break; diff --git a/externals/coda-oss/modules/c++/cli/unittests/test_cli.cpp b/externals/coda-oss/modules/c++/cli/unittests/test_cli.cpp index f0c6d506c..ade63b34a 100644 --- a/externals/coda-oss/modules/c++/cli/unittests/test_cli.cpp +++ b/externals/coda-oss/modules/c++/cli/unittests/test_cli.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -53,7 +54,7 @@ TEST_CASE(testValue) { TEST_ASSERT_ALMOST_EQ(v.at(i), 10.0f * i); } - TEST_ASSERT_EQ(v.size(), static_cast(10)); + TEST_ASSERT_EQ(std::ssize(v), 10); // strings v.setContainer(strings); @@ -61,7 +62,7 @@ TEST_CASE(testValue) { TEST_ASSERT_EQ(v.at(i), str::toString(i)); } - TEST_ASSERT_EQ(v.size(), static_cast(10)); + TEST_ASSERT_EQ(std::ssize(v), 10); } TEST_CASE(testChoices) @@ -161,7 +162,7 @@ TEST_CASE(testIterate) std::vector keys; for(cli::Results::const_iterator it = results->begin(); it != results->end(); ++it) keys.push_back(it->first); - TEST_ASSERT_EQ(keys.size(), static_cast(2)); + TEST_ASSERT_EQ(std::ssize(keys), 2); // std::map returns keys in alphabetical order... TEST_ASSERT_EQ(keys[0], "config"); TEST_ASSERT_EQ(keys[1], "verbose"); diff --git a/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/span.h b/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/span.h index 13cb37dc4..c69d055c6 100644 --- a/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/span.h +++ b/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/span.h @@ -23,6 +23,11 @@ #ifndef CODA_OSS_coda_oss_span_h_INCLUDED_ #define CODA_OSS_coda_oss_span_h_INCLUDED_ +#include +#include +#include + +#include #include #include "coda_oss/CPlusPlus.h" @@ -90,6 +95,29 @@ inline span as_writable_bytes(span s) noexcept return span(p, s.size_bytes()); } +// https://en.cppreference.com/w/cpp/iterator/size +template +constexpr size_t size(const C& c) +{ + return c.size(); +} +template +constexpr ptrdiff_t ssize(const C& c) +{ + return gsl::narrow(c.size()); +} + +template +constexpr size_t size(const T (&)[N]) noexcept +{ + return N; +} +template +constexpr ptrdiff_t ssize(const T (&)[N]) noexcept +{ + return N; +} + } #endif // CODA_OSS_coda_oss_span_h_INCLUDED_ diff --git a/externals/coda-oss/modules/c++/io/include/io/ByteStream.h b/externals/coda-oss/modules/c++/io/include/io/ByteStream.h index a64b7efc8..c8fc32a06 100644 --- a/externals/coda-oss/modules/c++/io/include/io/ByteStream.h +++ b/externals/coda-oss/modules/c++/io/include/io/ByteStream.h @@ -117,10 +117,13 @@ struct CODA_OSS_API ByteStream : public SeekableInputStream, public SeekableOutp return mData.empty() ? nullptr : &mData[0]; } - sys::Size_T - getSize() + auto size() const { - return mData.size(); + return mData.size(); + } + auto getSize() const + { + return size(); } protected: diff --git a/externals/coda-oss/modules/c++/io/source/ByteStream.cpp b/externals/coda-oss/modules/c++/io/source/ByteStream.cpp index bffd24aa1..7383011e4 100644 --- a/externals/coda-oss/modules/c++/io/source/ByteStream.cpp +++ b/externals/coda-oss/modules/c++/io/source/ByteStream.cpp @@ -20,6 +20,8 @@ * */ +#include + #include "io/ByteStream.h" sys::Off_T io::ByteStream::seek(sys::Off_T offset, Whence whence) @@ -33,13 +35,13 @@ sys::Off_T io::ByteStream::seek(sys::Off_T offset, Whence whence) mPosition = offset; break; case END: - if (offset > static_cast(mData.size())) + if (offset > std::ssize(mData)) { mPosition = 0; } else { - mPosition = static_cast(mData.size() - offset); + mPosition = std::ssize(mData) - offset; } break; case CURRENT: @@ -48,7 +50,7 @@ sys::Off_T io::ByteStream::seek(sys::Off_T offset, Whence whence) break; } - if (mPosition > static_cast(mData.size())) + if (mPosition > std::ssize(mData)) mPosition = -1; return tell(); } @@ -59,7 +61,7 @@ sys::Off_T io::ByteStream::available() throw except::Exception(Ctxt("Invalid available bytes on eof")); sys::Off_T where = mPosition; - sys::Off_T until = static_cast(mData.size()); + sys::Off_T until = std::ssize(mData); sys::Off_T diff = until - where; return (diff < 0) ? 0 : diff; } @@ -78,7 +80,7 @@ void io::ByteStream::write(const void* buffer, sys::Size_T size) mData.resize(newPos); const auto bufferPtr = static_cast(buffer); - std::copy(bufferPtr, bufferPtr + size, &mData[static_cast(mPosition)]); + std::copy(bufferPtr, bufferPtr + size, &mData[gsl::narrow(mPosition)]); mPosition = static_cast(newPos); } } diff --git a/externals/coda-oss/modules/c++/io/unittests/test_streams.cpp b/externals/coda-oss/modules/c++/io/unittests/test_streams.cpp index 63587403e..f3d777ed8 100644 --- a/externals/coda-oss/modules/c++/io/unittests/test_streams.cpp +++ b/externals/coda-oss/modules/c++/io/unittests/test_streams.cpp @@ -80,10 +80,10 @@ TEST_CASE(testByteStream) stream.seek(2, io::Seekable::END); TEST_ASSERT_EQ(stream.tell(), 18); - TEST_ASSERT_EQ(stream.getSize(), static_cast(20)); + TEST_ASSERT_EQ(std::ssize(stream), 20); stream.write("abcdef"); - TEST_ASSERT_EQ(stream.getSize(), static_cast(24)); + TEST_ASSERT_EQ(std::ssize(stream), 24); const std::string test("test"); { diff --git a/externals/coda-oss/modules/c++/logging/unittests/test_exception_logger.cpp b/externals/coda-oss/modules/c++/logging/unittests/test_exception_logger.cpp index 57016a0de..6084f1d87 100644 --- a/externals/coda-oss/modules/c++/logging/unittests/test_exception_logger.cpp +++ b/externals/coda-oss/modules/c++/logging/unittests/test_exception_logger.cpp @@ -22,6 +22,7 @@ #include #include +#include #include "TestCase.h" @@ -102,7 +103,7 @@ TEST_CASE(testExceptionWithBacktrace) } catch (const except::Throwable& t) { - TEST_ASSERT_EQ(t.getBacktrace().size(), static_cast(0)); + TEST_ASSERT_EQ(std::ssize(t.getBacktrace()), 0); s = t.toString(); what = t.what(); } diff --git a/externals/coda-oss/modules/c++/math.linear/unittests/test_Vector.cpp b/externals/coda-oss/modules/c++/math.linear/unittests/test_Vector.cpp index 1a4df6d46..4e912b21d 100644 --- a/externals/coda-oss/modules/c++/math.linear/unittests/test_Vector.cpp +++ b/externals/coda-oss/modules/c++/math.linear/unittests/test_Vector.cpp @@ -1,3 +1,4 @@ +#include #include #include "TestCase.h" #include "math/linear/Vector.h" @@ -256,8 +257,8 @@ TEST_CASE(testOperatorMinusEquals) Vector v2(5, -5); v2 -= v1; - TEST_ASSERT_EQ(v1.size(), static_cast(5)); - TEST_ASSERT_EQ(v2.size(), static_cast(5)); + TEST_ASSERT_EQ(std::ssize(v1), 5); + TEST_ASSERT_EQ(std::ssize(v2), 5); for (int i = 0; i < 5; i++) TEST_ASSERT_EQ(v2[i], -18); for (int i = 0; i < 5; i++) @@ -347,9 +348,9 @@ TEST_CASE(testOperatorMinus) Vector v3(v2 - v1); // TODO: Test what happens if v1 & v2 are of different lengths. - TEST_ASSERT_EQ(v1.size(), static_cast(4)); - TEST_ASSERT_EQ(v2.size(), static_cast(4)); - TEST_ASSERT_EQ(v3.size(), static_cast(4)); + TEST_ASSERT_EQ(std::ssize(v1), 4); + TEST_ASSERT_EQ(std::ssize(v2), 4); + TEST_ASSERT_EQ(std::ssize(v3), 4); for (int i = 0; i < 4; i++) { diff --git a/externals/coda-oss/modules/c++/sio.lite/include/sio/lite/UserDataDictionary.h b/externals/coda-oss/modules/c++/sio.lite/include/sio/lite/UserDataDictionary.h index 627c975f8..00aae905b 100644 --- a/externals/coda-oss/modules/c++/sio.lite/include/sio/lite/UserDataDictionary.h +++ b/externals/coda-oss/modules/c++/sio.lite/include/sio/lite/UserDataDictionary.h @@ -77,6 +77,7 @@ class OrderedDictionary } virtual size_t size() const { return mList.size(); } + virtual bool empty() const { return mList.empty(); } virtual void add(Key_T key, const Value_T& value) { diff --git a/externals/coda-oss/modules/c++/sio.lite/source/FileHeader.cpp b/externals/coda-oss/modules/c++/sio.lite/source/FileHeader.cpp index 8a7c8a40f..619f8af72 100644 --- a/externals/coda-oss/modules/c++/sio.lite/source/FileHeader.cpp +++ b/externals/coda-oss/modules/c++/sio.lite/source/FileHeader.cpp @@ -65,7 +65,7 @@ long sio::lite::FileHeader::getLength() const { size_t length = SIO_HEADER_LENGTH; - if (userData.size() > 0) + if (!userData.empty()) length += 4; //num fields int for (sio::lite::UserDataDictionary::ConstIterator it = userData.begin(); it != userData.end(); ++it) @@ -158,7 +158,7 @@ void sio::lite::FileHeader::to(size_t numBands, io::OutputStream& os) void sio::lite::FileHeader::writeUserData(io::OutputStream& os) { - const auto numFields = static_cast(userData.size()); + const auto numFields = gsl::narrow(userData.size()); os.write((const sys::byte*)&numFields, 4); for(sio::lite::UserDataDictionary::Iterator it = userData.begin(); @@ -171,7 +171,7 @@ void sio::lite::FileHeader::writeUserData(io::OutputStream& os) os.write((const sys::byte*)key.c_str(), keySize); std::vector& uData = it->second; - const auto udSize = static_cast(uData.size()); + const auto udSize = gsl::narrow(uData.size()); os.write((const sys::byte*)&udSize, 4); //Do we need to check for endian-ness and possibly byteswap??? diff --git a/externals/coda-oss/modules/c++/std/include/std/span b/externals/coda-oss/modules/c++/std/include/std/span index 407d7d54f..6eb29377b 100644 --- a/externals/coda-oss/modules/c++/std/include/std/span +++ b/externals/coda-oss/modules/c++/std/include/std/span @@ -23,6 +23,7 @@ #define CODA_OSS_std_span_INCLUDED_ #include "coda_oss/span.h" +#include "coda_oss/CPlusPlus.h" // Make it (too?) easy for clients to get our various std:: implementations #ifndef CODA_OSS_NO_std_span @@ -47,4 +48,50 @@ namespace std // This is slightly uncouth: we're not supposed to augment "std". #endif // CODA_OSS_NO_std_span +// Make it (too?) easy for clients to get our various std:: implementations +#ifndef CODA_OSS_NO_nonmember_container_access + // https://en.cppreference.com/w/cpp/feature_test#cpp_lib_nonmember_container_access + #if defined(__cpp_lib_nonmember_container_access) && (__cpp_lib_nonmember_container_access >= 201411L) + #define CODA_OSS_NO_nonmember_container_access 1 // no need to muck with `std` + #else + // It seems MSVC has this even at C++14, see + // https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170 + #if _MSC_VER >= 1900 // Visual Studio 2015 (14.0) + #define CODA_OSS_NO_nonmember_container_access 1 // no need to muck with `std` + #else + #define CODA_OSS_NO_nonmember_container_access 0 // use our own + #endif + #endif +#endif + +#if !CODA_OSS_NO_nonmember_container_access +namespace std // This is slightly uncouth: we're not supposed to augment "std". +{ + using coda_oss::size; +} +#ifndef __cpp_lib_nonmember_container_access +#define __cpp_lib_nonmember_container_access 201411L // https://en.cppreference.com/w/cpp/feature_test +#endif +#endif // CODA_OSS_NO_nonmember_container_access + +// Make it (too?) easy for clients to get our various std:: implementations +#ifndef CODA_OSS_NO_std_ssize + // https://en.cppreference.com/w/cpp/feature_test#cpp_lib_ssize + #if defined(__cpp_lib_ssize) && (__cpp_lib_ssize >= 201902L) + #define CODA_OSS_NO_std_ssize 1 // no need to muck with `std` + #else + #define CODA_OSS_NO_std_ssize 0 // use our own + #endif +#endif + +#if !CODA_OSS_NO_std_ssize +namespace std // This is slightly uncouth: we're not supposed to augment "std". +{ + using coda_oss::ssize; +} +#ifndef __cpp_lib_ssize +#define __cpp_lib_ssize 201902L // https://en.cppreference.com/w/cpp/feature_test +#endif +#endif // CODA_OSS_NO_std_ssize + #endif // CODA_OSS_std_span_INCLUDED_ \ No newline at end of file diff --git a/externals/coda-oss/modules/c++/str/unittests/test_str.cpp b/externals/coda-oss/modules/c++/str/unittests/test_str.cpp index 8fd60b90d..2d00862d8 100644 --- a/externals/coda-oss/modules/c++/str/unittests/test_str.cpp +++ b/externals/coda-oss/modules/c++/str/unittests/test_str.cpp @@ -21,6 +21,7 @@ */ #include // std::ignore +#include #include #include @@ -125,9 +126,9 @@ TEST_CASE(testSplit) { std::string s = "space delimited values are the best!"; std::vector parts = str::split(s, " "); - TEST_ASSERT_EQ(parts.size(), static_cast(6)); + TEST_ASSERT_EQ(std::ssize(parts), 6); parts = str::split(s, " ", 3); - TEST_ASSERT_EQ(parts.size(), static_cast(3)); + TEST_ASSERT_EQ(std::ssize(parts), 3); TEST_ASSERT_EQ(parts[2], "values are the best!"); } diff --git a/externals/coda-oss/modules/c++/sys/unittests/test_NaN_testing.cpp b/externals/coda-oss/modules/c++/sys/unittests/test_NaN_testing.cpp index 82df40509..859e37b20 100644 --- a/externals/coda-oss/modules/c++/sys/unittests/test_NaN_testing.cpp +++ b/externals/coda-oss/modules/c++/sys/unittests/test_NaN_testing.cpp @@ -21,6 +21,9 @@ */ #include +#include +#include + #include "TestCase.h" TEST_CASE(testNaNsAreNotEqual) @@ -58,9 +61,40 @@ TEST_CASE(testIsNaN) TEST_ASSERT_FALSE(IS_NAN(std::string("test string"))); } +TEST_CASE(test_ssize) +{ + // https://en.cppreference.com/w/cpp/iterator/size + + // Works with containers + std::vector v{3, 1, 4}; + TEST_ASSERT_EQ(std::size(v), 3); + + // And works with built-in arrays too + int a[]{-5, 10, 15}; + // Returns the number of elements (not bytes) as opposed to sizeof + TEST_ASSERT_EQ(std::size(a), 3); + static_assert(sizeof(a) == 12, "sizeof(a)"); + + // Provides a safe way (compared to sizeof) of getting string buffer size + const char str[] = "12345"; + // These are fine and give the correct result + TEST_ASSERT_EQ(std::size(str), 6); + static_assert(sizeof(str) == 6, "sizeof(str)"); + + // But use of sizeof here is a common source of bugs + const char* str_decayed = "12345"; + static_assert(sizeof(str_decayed) == sizeof(void*), "sizeof(void*)"); + + // Since C++20 the signed size (std::ssize) is available + auto i = std::ssize(v); + for (--i; i != -1; --i) { } + TEST_ASSERT_EQ(i, -1); +} + TEST_MAIN( TEST_CHECK(testNaNsAreNotEqual); TEST_CHECK(testNaNIsNotAlmostEqualToNumber); TEST_CHECK(testIsNaN); -) + TEST_CHECK(test_ssize); + ) diff --git a/externals/coda-oss/modules/c++/xml.lite/unittests/test_xmlelement.cpp b/externals/coda-oss/modules/c++/xml.lite/unittests/test_xmlelement.cpp index 0c252e12a..2f42d5b38 100644 --- a/externals/coda-oss/modules/c++/xml.lite/unittests/test_xmlelement.cpp +++ b/externals/coda-oss/modules/c++/xml.lite/unittests/test_xmlelement.cpp @@ -21,6 +21,7 @@ */ #include +#include #include "coda_oss/CPlusPlus.h" #include "io/StringStream.h" #include @@ -101,7 +102,7 @@ TEST_CASE(test_getElementsByTagName) { const auto aElements = root.getElementsByTagName("a", true /*recurse*/); - TEST_ASSERT_EQ(aElements.size(), static_cast(1)); + TEST_ASSERT_EQ(std::ssize(aElements), 1); const auto& a = *(aElements[0]); const auto characterData = a.getCharacterData(); @@ -113,7 +114,7 @@ TEST_CASE(test_getElementsByTagName) TEST_ASSERT_EQ(docElements.size(), static_cast(1)); { const auto aElements = docElements[0]->getElementsByTagName("a"); - TEST_ASSERT_EQ(aElements.size(), static_cast(1)); + TEST_ASSERT_EQ(std::ssize(aElements), 1); const auto& a = *(aElements[0]); const auto characterData = a.getCharacterData(); @@ -137,10 +138,10 @@ TEST_CASE(test_getElementsByTagName_duplicate) const auto docElements = root.getElementsByTagName("doc"); TEST_ASSERT_FALSE(docElements.empty()); - TEST_ASSERT_EQ(docElements.size(), static_cast(1)); + TEST_ASSERT_EQ(std::ssize(docElements), 1); { const auto duplicateElements = docElements[0]->getElementsByTagName("duplicate"); - TEST_ASSERT_EQ(duplicateElements.size(), static_cast(2)); + TEST_ASSERT_EQ(std::ssize(duplicateElements), 2); const auto& duplicate = *(duplicateElements[0]); const auto characterData = duplicate.getCharacterData(); diff --git a/externals/coda-oss/modules/c++/xml.lite/unittests/test_xmlparser.cpp b/externals/coda-oss/modules/c++/xml.lite/unittests/test_xmlparser.cpp index 3dad8420c..e35911651 100644 --- a/externals/coda-oss/modules/c++/xml.lite/unittests/test_xmlparser.cpp +++ b/externals/coda-oss/modules/c++/xml.lite/unittests/test_xmlparser.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "io/StringStream.h" #include "io/FileInputStream.h" @@ -105,7 +106,7 @@ static std::filesystem::path find_unittest_file(const std::filesystem::path& nam static void test_a_element(const std::string& testName, const xml::lite::Element& root) { const auto aElements = root.getElementsByTagName("a", true /*recurse*/); - TEST_ASSERT_EQ(aElements.size(), static_cast(1)); + TEST_ASSERT_EQ(std::ssize(aElements), 1); const auto& a = *(aElements[0]); const auto characterData = a.getCharacterData(); @@ -124,7 +125,7 @@ TEST_CASE(testXmlParseSimple) const auto docElements = root.getElementsByTagName("doc"); TEST_ASSERT_FALSE(docElements.empty()); - TEST_ASSERT_EQ(docElements.size(), static_cast(1)); + TEST_ASSERT_EQ(std::ssize(docElements), 1); test_a_element(testName, *docElements[0]); } @@ -365,7 +366,7 @@ static void testReadXmlFile(const std::string& testName, const std::string& xmlF const auto& root = getRootElement(getDocument(xmlParser)); const auto aElements = root.getElementsByTagName("a", true /*recurse*/); - TEST_ASSERT_EQ(aElements.size(), static_cast(1)); + TEST_ASSERT_EQ(std::ssize(aElements), 1); const auto& a = *(aElements[0]); auto characterData = a.getCharacterData(); diff --git a/externals/coda-oss/modules/c++/zip/include/zip/ZipFile.h b/externals/coda-oss/modules/c++/zip/include/zip/ZipFile.h index 6e7c7e6e6..b81927d74 100644 --- a/externals/coda-oss/modules/c++/zip/include/zip/ZipFile.h +++ b/externals/coda-oss/modules/c++/zip/include/zip/ZipFile.h @@ -23,6 +23,8 @@ #ifndef __ZIP_ZIP_FILE_H__ #define __ZIP_ZIP_FILE_H__ +#include "gsl/gsl.h" + #include "zip/ZipEntry.h" /*! @@ -144,9 +146,9 @@ class ZipFile return mComment; } - unsigned long getNumEntries() const + auto getNumEntries() const { - return static_cast(mEntries.size()); + return gsl::narrow(mEntries.size()); } }; diff --git a/externals/coda-oss/modules/drivers/uuid/CMakeLists.txt b/externals/coda-oss/modules/drivers/uuid/CMakeLists.txt index a041f1452..0a437f6e0 100644 --- a/externals/coda-oss/modules/drivers/uuid/CMakeLists.txt +++ b/externals/coda-oss/modules/drivers/uuid/CMakeLists.txt @@ -42,7 +42,7 @@ else() coda_fetch_driver( NAME ${TARGET_NAME} ARCHIVE "e2fsprogs-1.47.0.tar" - HASH "SHA256=dbf5661535cd19f2eab0915442b2ad2b8f1f471b039b92c79bed7f53bab8dccb" + HASH "SHA256=c7c3a26bee8bb3b0041ee8701a5f47a29e81ee0b20d5995bc4544638cd0ea394" ) set(SOURCE_DIR "${${CMAKE_PROJECT_NAME}_${TARGET_NAME}_SOURCE_DIR}") diff --git a/externals/coda-oss/modules/drivers/uuid/e2fsprogs-1.47.0.tar b/externals/coda-oss/modules/drivers/uuid/e2fsprogs-1.47.0.tar index 1c839924ae01048c4dc7a89b75e46e338094dda7..9d1bfa2cea1e6ab9f841a7e52b1e09fa07dce339 100644 GIT binary patch delta 24611 zcmZvEYjBfSmf(EG*2~5ZSqNJeZUV;8HW=H;vgO#ao3ex-vM`Qquq{83ge*Urkc>k! z8H#2I0g9psAprsHW?7mcREA~xkbu9@FM{KyOBKxDwI!jVn$=}Q@M%*7M%KtlM z7%&Ul9p$Cs_H^Z=4Eu_Nva*kc?F*6?#doTTqF0p96LJT>!o@p9i9j)7)z03MqZ26sh|kEErIB=ca5;nNZ-9 z0G}!FNmNrNl6syak~{kB*yd+Ci@HyjJ_y(+bkRgyIG2;XXS3e&0=!*p_z2`D0sxepJ zZw8PLhk@u~04UQ?sLFdTMNtz<^#cir!=azAD=h{!XySR#WmIDS=YOm=#cpqEOO72n zt1na=o%){@BRGm70vJoh9SmbsKahwZX1y);{)pZ(NjE!`QMFp%&j?4V*1ihII*lqb zllHqJ$S2GQVy(YyF{_#D^&KRDaT6Q`!he~+EgCi3WdUkPVn>RXz81T^)@+VFJeiRk z`|s~1&WJ6{Fk52(uDsHu?%1LKuXB-`QV&pa8YqctK?N;DvvCouJhu58Sd`?;SpAk1 z5F5S&=S!9b_4UL*zgS(2+D4dbfV}J6m?3jA(Ai&GSiTmv`8=pf|Bwo0*GLN zAG9PZYRXz;4>7XdD96jczRpy#!PqljFb{{b93&^1$8n<=g^G(otJ3-jVI58Y-AKzP zjTEFV8A0VIjb@3_&y3M2CYl#yH4ARBZT?QPRR^#wm)Lc-gp$%nAMP ziZMgobKW}w=Jbs*ng!cF90sA>1EC0k{WBvI?R{gAcJ509kOxfsabv}U9~uW407jul zKvrDxxcXRFePXmEmCKudpyk+bkYRrc1jMZow~uS+!GvVRhV3qpW}+!mW{vr(&cyu?1#U2zrKDptae*V_DJDraAEu=!>eN(I zfMk)iU73`F6i`P?ex+YS!CopOpzcO9g@HI zRS5QJ2ySPCh7SO35{C@Sm_|NgIRsdQdW6V0tYJY}9x(~luPXm&it3SyeQ6+}<0goe z`+~sU35~szCOIvT>`zJRKMlvmBLYh84BO74J^IX969mJn%UE5Ls3x8>tzvEy8%E=} zDjNr(|Ble3Ut9x%9Rm#vJ}W2@Fqv0H+Iz{YO)VqM9F?mJ5FU$RvkVRw1ehk4;$BAd)9wzhY|r z-=@fvcr=`^TO?JzELV=3C|8b~SVbh9Px1JfDUc}aFL@!D?#W1I!4Trop7)b8lgi^E zA4QOmEID_wpYt72doAb-x#?0rRG9aP zq8^)>{zW&gu1{Z}?(-%`mAz{!4O=rtsL?lPgbEP;M8y29%n0`4x+4O#rJ4l>RVB?FosElFpO=~i4G4tCfbbFZJ%{-orRplPoRU9k zWe2&*WZS1Qf9gMy0mJsRTB7(inzWdU` zjbuCsk?NrZ;^X#0w(!WpNlcg~rIqiydz9F(Po$aEHHp*4|9*;-)k_6=!0E&T3tgxUrviy21RwD)_ zDe*h4lU*9jqay;#yuH zg*TU#bqH&%0WyLe4A)sZ!?n}eL*90lebCaMA`m=key++rJW+vDt?Ep{}_Y4 zV;co34`v5aZ~<$cPqVQWVmpp!caiBAw19n`%$Dry&)F(!`^*P8;PFVo_3Wj+|K?L?D#IbOFIondyJ&r(GJ28dT$c=es&k}hjqhaM)P8%`AK$wNPC(M z*1aQ}9XXyIAOTGZ%Ef{P8YO@f1stvG&5lgx)K*p4uw^4mCDD4Y&P>1||Tg^jBs z%m`YGz!4kQ0unUD(C@;95se@`cP+y*WMd*;r=j0ylgw$kjj3#tjoSfk+r{t^=esp> z57^*uXO*X)u*~ZX3)(o3`cvFC^To9IkD& z^O-s5#h|B@SvfsqOvp=q&a^-5M^~Mf!zV(>N>L67_+Sp(P@K~vSbb#<@Yux`rdH)} zt4G5ddN-IFgnj#8TPkxddQB^=r^)sci_S%jZR%3 z#NaJCW^G}cMh_CYo1x!=^n9GdO*6$0f%hO=$j5UJ<@DHiFo1Ip<}m*`pTmt0#c*j7 z%jF#IKjT3V^0!QIMCnzH`g@FeBJzGt5BZOy8HgMQU|^NW=9z{CWV2_p9Z2~WzfZ7p zwP4|IVhgk(#U8LDjq~h)eZ_*r^ z*v{x#ZI81HT)k@tvm>3X*LI*ZH^IWb<9PUHJD288J9sB5c9(sSXhhiK4EtHcenNvS z^?(@8+NG(+dv=x`&e;QGquaeez*W1{auLXPb}o4=G;T2T^UySJ+IuLoprJjPT=>Dx zGXhrB6O1d$JJ0PsR7b-+W6$OpfN2d1E@4IwQGrL;CKv28_z^qpU^}HV&NYK8G~fiLo=j0VR%OLzo15IbA`_K6Xk!6DqEGs zx$yZJd}gZ3;@6_v5b*MAQXxktUU_ZRd@>AJ6$VI)1{0O7NzY!3B|V!Jr^3P@& zSsN`?1{1TEQ*ALZ3&yiTZSk9qSxT(E2zo;2^I3~(@ff_9anF9a*{q$-i+z+%{cNE& z#I~q$HV*}@v!#ZF*l3%*Y7^qW2CG6#_PvW0$k%5FNrw02RjSkP&kh#hUX0b&JW$yB z@M}oE2^q z2tWjHp(=Z1?f^*`J%0m$#3xRScvh`%oI5~qZ)~o7S@L6{PT8tII9JsloELnKl#cxz zZp8&PG7wn)dGKvqPA`yqL0UE!1RvvaLLpd4r0^~1))Nc+g7}>y0@e{Jggo@n!VElG z7$Q+_XTZKTFsFk*H>su_g?&S~;c1}|Ted1c7OKjR^P}y!=35|%`NzVkikj+Q&^<=0 z?AqzU0;#S2v5F=+vGqc%Lw2~@@z2bgVq1AmwE7v0e%R(@!$Egr_tqTV`@GDAy3oTOL z^jj}e#_EMZD$3DZ-(4uR_yn?kVUT2ea3RQeo`>~*hZcs8B5H53B*U^2hP1vo_z+jE zPDmh*5{a3zlISvA+)@JLV{zy}fpA+%_^8k`7L{hwLQcskW{!3MS>I+eRb*Uk#48}!Lm|s&WHGqznUK6}sN-^v0Qebo>G@xu5Ej=^3 zXmA(Oo9Gb2Hb!)vWAHRCopUS@dRAOJ?-;y-Ygd+uKbLU_M66-7%6u`*LR8&hvc{@e@k#gA3!V(P%V5EF%3y!j(XJ(4srF#o zVp&}kpo2g~9fj1@6;jH1vm#oKIFD9*iQRJC)H?KUQSuoMPf8iq2KElX9*C zR$(kkvzPBc`EPz#F}_fAi9{D0VM3B8pMYBfSC$gX*17y~D7dgGiPuINfI$F&#}Os$ zT0}-+a*;9NMB3znn-igwnBihkHO19Ac`E~07L~z3PR5eXv0wsAcR|>!aKXSk!R%T! zd0_-wizlyCG!nD;R-E!@xh$XW*MZ>>RR@?vf-w!-b<`oR80R3FA5R+gaK!ybj58 z3G;Pa&)3%Ruz9c^7eB5SXzLp-;Fa@18shMqq*3JR)Coc_D~CipDU6v)>@}y$8wWsf zy#!I=VzC3~*A+m7P%+XYp-NY;B=Pdew^2-N><~Ai;I~X-w@4!grKN+RsyB zbG)uPwBvdg%#h23S!a`rE!W4F#SqCzV5^P7>LOuA+vJKW9BZMzWRdeFwEp-;ST8P> zwlc&md>!v7T3i`wtj#s3?2WWQanS1G_cDy+GVzL%v6$Y@wMd<^bYzOc!D3I=2cY^(*1z;xG1wx4X8I17p?cr`$FZG((@g4wIo4kn9 z?wQ710qq)Rc5LTCS28RT)@QayRw#p}s&c^jG7GuHr>p;+x3Dl@^-g|JLLg{hMFhoe>q zR`yD%pP}9|w=zic21lio;%L=b8Km62q8|{feiec>8Upl(EtT?f0-|GECBI6*N_DJK zkguxz$q&y8+H)(@)z=PI)>E~LOnq7jvbZ-JD&6Ci{1FuHzremfuYh>}`+%08;o4!jP7e8E#`dF=JR6{z_iUY9oi_4Vk_@q0Wmw@RY;%^<@( zv#O7XMaJjLAXHixRRt*yEUscj`zVlH>IIVPs)7ZG9p}fZtHdONj=ZLd&l1oe*8y(9 zJ4mMQR`EB1IP~0DCFzzxHdXN(uF6J;bz1<7&=Hc&ZmSxg@Q$8(1+WMP`scbnMeYBl z%18$KZIzT~$quhpp&jD2%I_OwN{6y6vm1u01Nwyy{wV!t>$VA z!hr%l8c~F+`Gf@rle>Ur!88bDcXg03qg2L#D=}CR%)x3tDmha9!rd^fAJx|J>E-ci zd0_MVYJLZaC!7T$1hXLo=QIRZC|!g*?tLb9WBs_zpc=lcUP<8;_g{kj0-q%I%bM6x zJl~3{)$UoZYJx&6*Ip%x>lzj4X}7ASp%EQ)yPCgbysOE22pUHZs zT@%%zO0=9ORS+4SZpm?IW>ewjfeFd0bH9Q~ubbPJ&nc<6S5X8VfIx7d z9yc2rtZ?&de>@}LX479c7?Hl$&Gn0B5|;N8`iPsG38G&EAcA%OSjgU*yzTC%3zTv8 zj&ZG9dPzuF*13ZOf)ZX2f)MPH!r%spk1aAS1hP%TlDY&A+Tl*uLsul^Ga5YX)DZ0j zaS6ndGw*W`_)%OK%kBXsf>BW{yYI$WhSBPQ+a$_Ush+09tPkDGv{)1S;Gx?nRY(N# zh=Z`-ejpW-*!{+2M0pIn3Ne>V=ZU6ttPaP4P66a6H-GqoN|}KD0u!|Vxtqra z%#sN;;^;tgjl>$B`7wW4YlJ9)?YOFB)kGhGhI<9Ry&9?!%2*nWjMVUV zU#o%6mrhty!{swt0}fpPGm|rGYxo@n7FnBXGSygD+Mse~OAWtGL{T0DQHs|CM9m>h zlz206ss=_ILXIHwJzc{+6>ogb*GQ)KlbcNyFVu*4)nCcdBP?HQSRBoeOUhWUPE#?S z%f7AQxeU3u1}FsEpy}H68vcOwdKCQVF^EnG%>PguRX!PfQbWlB^U(y5DnPvD@hGbI zdChDB!PsG_eT5cHwLE#D4O?m@8>Yl(t>uX?t5(Xq!!uIhvf5VLMRmbySdBBPneUof zZfZ!u##&h~zz5CF(1dots;Cia9(LC9-$P)*{&6h?Mgvsj@NTR&N>w`6O{Z%i9|xvG z%zq9>k$I-JgMt}eo1A02tn8ZieC;4j+R#p}!HJU@6$`fOwY)+_k{+;)XZzVC^wD#0TKcwF#`ZcYYPZ*cYaeKWtoyts zT}|In*GXBoAP;iZ?mF|U=CdEyt#V@kL(N{TlQQO?>jtJwf#1XNcZ=8RK=gw7km#@1 zq3AKl-l~I_I&p%vcI$SX){?c~3qR~>hNi1;bo7w*<^UwBX_ zg(`A`hjpvyG6j=TiYHUh7e|ol;n#UM;oO&Jzfs4Q`GcLo=(DqH*GsTl4p`N?eg&CfGi#c`h}D| z-O28Gk9bxQi=$yy)`|m|f2d{e%s=%kCtKR?{aI}LNl&WuV<$3%Qy%VvXMy&Y!t^;0 zzeu_CB4-~=QFmSO{M%II4`0jQ0RHx$&13?(>EY2G!|`q4Pr&?^r+-T9f2Pl!6HEIK z9-DgTuIEolh~)vCAuvgDcwf<5uiW=zyZp9I3q3sTrbkr(T0k>V06K1CgV~s&(UrmT@WuhSFLxI zcQQh30ki@L)mhuTh6IWe+r99dFV31a+S%cq3=zA%=>OXN4|R&~OzRnW8IFMJ^so%BM% z2gJ&;=#-aY5qkS6CMC)wr@cIa;BD%8pfN69RiS$5f|uW>-ta;gsDmq~GdI11H2=4< zTcL-bHF?ie3=xnbU6KN5W^DvlAJ2roXzyNH4 zS}$cOnr)}o^WW~G-puu&x36lLbzADWbWv~iddaq^smZMm(k(bf$Vvbaq)Q-G^}O%F zI;s{ZkU$ubi|bcX9fc0+0}z4B9}5|XzkVgDpru~$G^%o2>!Y+i0BeHzPj6u6-&-Fz zh7!;<2s`203|9>e{K+KpXl;-fnBEYbLE2$IRCP2+q)%^Pw}Z}xH^{sy0lT0(8v0Z< z4CEmKyjAW8>@R@?8wO?}2+p211Bk%;vL$B0XuO*_Cq6g)QLvP0VqH`ZwyhPircE1Bnu-DcN0f| zAYK3wOo%}0HISBi@P(EpDUd8{;*ACxK>!woOh#d#w}~4lU9~p>@%7Ch9h~zHH3g~K zL+NaS^946v)?`!EoXt&svQm7Cy|W2S_-FQpi{q^Cd2c-C8 zO|Ov8r%k-RI_!h=c(zHbAGFJdb4|QQLjun;>a9+8`UUOuOHI&1>|!r(FE{bR7=`g& z6a3gJZf2S(-fa2{{hAr^-ENZ2fz0*327|rSL*RJdHTIn4Q4?>Wz?t{F?-Q&O7xh3N&3R@bUL&=pn)im21?8=$Oq7*+*SrK0MH zj}PMU0q#+sS-OZP0*?`a7;R4YUWhgQ$rqr24u zRRVVn%{(w+`O^lAacjYl+M!{_0&)eMxc{*eiqEcQenE_{mU`KV8|E^9?{ALOYXlx^ z&XnJzka2w4%&SEt=yzLM{ZBOWXm}Q+5GP41w$C+3d?aaXsdRq%MwgB;_*ZH- zy7?*asG+#T;b3(=<;Bkxh5ZOQ#ZLo{6uq3}eV8zx*)vPyT2o;=Ku{3cS-z*DZf9 zl^cmmC7Ot0-O>(P#c9?2rEuifTvn?VEe+AM3Qfef^c7XSe<`0Z)%U8z6Vc;Vtv2MG^*1h zEv-~`VqrPdA{CZ|YNQ38E3ygHPB=(NrysOLUqen$GMZS0a^_UaU;$|aKn3q1M7LUk z$8i;FpY6+Dan_DyybZuRtYgch$WWMfSW$oX>9VgW2V;OaxeR>!>kf8{cWN2$p>a-e z0rm=!^sT-(6?M(UWk1ocCQ&(;mc1Zr_BvgieR&!5((DrG>M|(`5)#5%>?)-X*P3RZc0fQvR=zqq& zU2jO=FYNtiMLijK<6qvvRcv&xz5y{Pu?V#C-5dOF8#{xW@cq8WH87$aF+e?e>kZx$ z(DbcMnyZk+^V+_q8Ut-)UYq>1o#IeI8yE=_i?2-*8vU5i-}c1CLLRO=uWUjv9>z=Y+JM#aqz$pENFztyp_7|B3grY?tHUnPV7 z)0gucWLYjn3X+L+`4@vE{N*5%tIL>7HZ50mn^uI@;rD1Y&sIo03BTi*Sh0wjO3Zw< zor2ggGcNArr{faKUHy6at` zjVPvjqu|afx}p3%xR8aTu5O;aF~bD9CHa+=q$_GhZ}$qyHS4?Or~hRo?5)OzZvM9c z)XV?|fisF#o4dVK-R|s`LJif|ySn)gIPj9}t8OVG(m#`Y-OcN36zdh4%D*(#DXQn2 z?mUWzXt~#95Hic_-8>`S0y2aY@qKsnU%5d-`FbEA6rE@rV*zd(NZ=t@k2?jf9}YzM z#1YRv7LY_hUh`?7ox_|ANQaXOPX)peDuJ?kURY+8i>;?UpO*22+MX9qV5YaY=a0Nz zt?yYNy*?!mYV5fA zzUe9DlM=i$Gxx%Aaj~&T$M~}Jw%h2qqF$g`C@2>84*W{s_-L=0-TX_Y&zL^et1*p! zeWF*cK8fg)y?^Ab2Nr0jffT1e%Afq!1a-RFyDWnaywodc0D0Pcs|9`xcDc879>HMn ze$p!?{@-*QRn$*@=>3Avmr=|U>@cApCcdBdwsSG-`XJT3v~K8Y=MyAEV(x<(m=wra z1z_p(a3q*X?R_s$!(ejbFqp^l`yh`CtWzGJ*B9caVYN`&2XAst1_q((bMy_Q5W}@V zr`Xq%O)c)bxPaENnpx8ajjxbX-s&x^1XZt z4{uIO`wjTBBB|nc^i#!;m6)SnC?NR>&VJs2p&3^7%LYs5xcgny7_8`*sGwS^tDirG zT+Y$Wf-wg7*KOB2*fDQac zVq=g`jIkKq9)#TT2>vwyhEec8e>;M`!j03upinAebUP5_(Ql#=qT@kWmqI7|(+77y z{P5sV@TY3Bg;6Wym|H>VUz!AdZwE`QlXojmgGLNil2*t0uL#G1LE$vIXL=S~WkI=M z!buIu!^wsa^sU3`q32ZUU}IqmNjZh)m-Z0<$4xZOnIS3j(O=Qb3U#r}hwXW72&DGa z63EE8;kgO1xpg5nlEI}q*cDo46%8T$|1#X#^3v8;Z7cpfw++^X zphskNgu3W$F1E`ffL%U)wT1!*t7}4F2WCAG{3O0l!+oIKt zA^z6{hQszHG5A#O}N0sTvw-4zN~()Hk|8RT{uC}jT=rd)xg3c7)5-%lM0{&NKo3KmRx(C3l7uiAiGXQJcp#aUF>a)WA#Mp`o)WGH8)^*g zN&0Z+ti7qBpT&M=4L8sRG$?CW;9R@Z%L+#l84N1c4kwDQPsrwS!;yqI$jq=14^cX^ z!cko2|2Uc_o`L}RaR5}nJfM3rC?iBc9AbVLGE1B(Tr7$&qJD~*RAh+KaCDLf=Su`u zFa-F{1M^ZPAaDrjgk)b8?lch429VtLx^OD~N3yI%Z+Hd$yaz{;jbWqk|Cp-M9A+~~ zU$`0L1bb08H`xgzpR&?oFm>%Jq&duA`64m?FgWPV7O?Y{Fz+Ps`xU^2pn8h=x7*X`T1<1W^I_? zrC=Ce4_MUbMFfJtI|9Wc8iBK%9F_DEr8B+e?B_s5a6m*u&aK(q$plFeHrCd1C|q4qEHpy^uu`in4vrdpG)G zX1u3uehixhJEZvdBsxHoIh-xn2VeBS+`&Og{iTCaBe`fW`WZ?M=TN7+U z@EKMUY$F3}QT4k<;Aiqe>Cal-tqHqF;PXrPtcK5<@L2<&x8U=(ny~wC2X-NwvqlBs zA$fVDgJ0s(J#k6JzmkK$2OZ^q_K4g+7!|M7ar?tjEibeG{&+kJ5pjsUdV4a;|L%m| zQ@kSu2C8$@-{BJk^eFQ?aIYgVl>pZWmUsAn5M;e0NrwKc!}iYBB->i}{7Ox-tqYR{ zJaR+HU$@RU8Hqlp8NYWORs2}|c-ILO@hDKgj=us%KWPLAA^g*Im~S0-KmWQH{;ibe j4K3>iK1FFhTPM*=dY)Lvp9swQJE2Bmay**%cXj_C{d^3{ delta 24559 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