diff --git a/3rdparty/astc-codec/.gitignore b/3rdparty/astc-codec/.gitignore
new file mode 100644
index 0000000..9e28100
--- /dev/null
+++ b/3rdparty/astc-codec/.gitignore
@@ -0,0 +1,5 @@
+bazel-*
+.bazelrc
+build
+.vs
+.vscode
diff --git a/3rdparty/astc-codec/BUILD.bazel b/3rdparty/astc-codec/BUILD.bazel
new file mode 100644
index 0000000..ea5a2c4
--- /dev/null
+++ b/3rdparty/astc-codec/BUILD.bazel
@@ -0,0 +1,29 @@
+# Copyright 2018 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+licenses(["notice"])
+
+cc_library(
+ name = "api",
+ hdrs = ["include/astc-codec/astc-codec.h"],
+ visibility = ["//src/decoder:__pkg__"],
+)
+
+cc_library(
+ name = "astc_codec",
+ hdrs = ["include/astc-codec/astc-codec.h"],
+ includes = ["include"],
+ visibility = ["//visibility:public"],
+ deps = ["//src/decoder:codec"],
+)
diff --git a/3rdparty/astc-codec/CMakeLists.txt b/3rdparty/astc-codec/CMakeLists.txt
new file mode 100644
index 0000000..4ecb921
--- /dev/null
+++ b/3rdparty/astc-codec/CMakeLists.txt
@@ -0,0 +1,46 @@
+# Copyright 2018 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+cmake_minimum_required(VERSION 3.1.0)
+project(astc-codec)
+
+option(OPTION_ASTC_TESTS "Build all the unit tests." ON)
+
+# TODO add support for the fuzzer, it has some additional dependencies we are not
+# yet bringing in.
+option(OPTION_BUILD_FUZZER "Build the fuzzer tests." OFF)
+
+set (CMAKE_CXX_STANDARD 11)
+if(OPTION_ASTC_TESTS)
+ enable_testing()
+
+ # No need to build gmock if an external project defines it.
+ if(NOT TARGET gmock_main)
+ # We use the approach suggested by https://crascit.com/2015/07/25/cmake-gtest/ to download gtest.
+ include(ExternalProject)
+ # Download and unpack googletest at configure time
+ configure_file(GoogleTest-CMakeLists.txt.in googletest-download/CMakeLists.txt)
+ execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
+ WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/googletest-download")
+ execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/googletest-download")
+
+ # Prevent GoogleTest from overriding our compiler/linker options when building with Visual Studio
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+
+ # Add googletest directly to our build. This adds the following targets: gtest, gtest_main, gmock and gmock_main
+ add_subdirectory("${CMAKE_BINARY_DIR}/googletest-src" "${CMAKE_BINARY_DIR}/googletest-build")
+ endif()
+endif()
+
+add_subdirectory(src/base)
+add_subdirectory(src/decoder)
diff --git a/3rdparty/astc-codec/CONTRIBUTING.md b/3rdparty/astc-codec/CONTRIBUTING.md
new file mode 100644
index 0000000..939e534
--- /dev/null
+++ b/3rdparty/astc-codec/CONTRIBUTING.md
@@ -0,0 +1,28 @@
+# How to Contribute
+
+We'd love to accept your patches and contributions to this project. There are
+just a few small guidelines you need to follow.
+
+## Contributor License Agreement
+
+Contributions to this project must be accompanied by a Contributor License
+Agreement. You (or your employer) retain the copyright to your contribution;
+this simply gives us permission to use and redistribute your contributions as
+part of the project. Head over to to see
+your current agreements on file or to sign a new one.
+
+You generally only need to submit a CLA once, so if you've already submitted one
+(even if it was for a different project), you probably don't need to do it
+again.
+
+## Code reviews
+
+All submissions, including submissions by project members, require review. We
+use GitHub pull requests for this purpose. Consult
+[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
+information on using pull requests.
+
+## Community Guidelines
+
+This project follows [Google's Open Source Community
+Guidelines](https://opensource.google.com/conduct/).
diff --git a/3rdparty/astc-codec/GoogleTest-CMakeLists.txt.in b/3rdparty/astc-codec/GoogleTest-CMakeLists.txt.in
new file mode 100644
index 0000000..569f4df
--- /dev/null
+++ b/3rdparty/astc-codec/GoogleTest-CMakeLists.txt.in
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 2.8.2)
+
+project(googletest-download NONE)
+
+include(ExternalProject)
+ExternalProject_Add(googletest
+ GIT_REPOSITORY https://github.com/google/googletest.git
+ GIT_TAG "release-1.8.1"
+ SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
+ BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ TEST_COMMAND ""
+)
\ No newline at end of file
diff --git a/3rdparty/astc-codec/LICENSE b/3rdparty/astc-codec/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/3rdparty/astc-codec/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/3rdparty/astc-codec/README.md b/3rdparty/astc-codec/README.md
new file mode 100644
index 0000000..398de14
--- /dev/null
+++ b/3rdparty/astc-codec/README.md
@@ -0,0 +1,71 @@
+# astc-codec
+
+astc-codec is a software ASTC decoder implementation, which supports the ASTC
+LDR profile.
+
+Example usage:
+
+```
+#include
+
+// ...
+
+std::vector astc = LoadMyASTCData();
+const size_t width = 640;
+const size_t height = 480;
+
+std::vector result;
+result.resize(width * height * 4);
+
+bool success = astc_codec::ASTCDecompressToRGBA(
+ astc.data(), astc.size(), width, height, astc_codec::FootprintType::k4x4,
+ result.data(), result.size(), /* stride */ width * 4);
+```
+
+## Building
+
+### With bazel
+
+Install [Bazel](https://bazel.build/), and then run:
+
+```
+bazel build :astc_codec -c opt
+```
+
+astc-codec has been tested on Mac and Linux.
+
+### Run Tests
+
+```
+bazel test //...
+```
+
+### With CMake
+
+Install [CMake](https://cmake.org/), and the run:
+
+```
+mkdir build && cd build && cmake .. && make
+```
+
+Or open the project in your favorite IDE and import CMakeLists.txt.
+
+### Run Tests
+
+In the build directory, execute:
+
+```
+ctest
+```
+
+
+## Contributing
+
+See [CONTRIBUTING.md](CONTRIBUTING.md) for important contributing requirements.
+
+## License
+
+astc-codec project is licensed under the Apache License Version 2.0. You can
+find a copy of it in [LICENSE](LICENSE).
+
+This is not an officially supported Google product.
diff --git a/3rdparty/astc-codec/WORKSPACE b/3rdparty/astc-codec/WORKSPACE
new file mode 100644
index 0000000..83fd282
--- /dev/null
+++ b/3rdparty/astc-codec/WORKSPACE
@@ -0,0 +1,37 @@
+# Copyright 2018 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+git_repository(
+ name = "gtest",
+ remote = "https://github.com/google/googletest.git",
+ commit = "ba96d0b1161f540656efdaed035b3c062b60e006",
+)
+
+http_archive(
+ name = "honggfuzz",
+ url = "https://github.com/google/honggfuzz/archive/1.7.zip",
+ sha256 = "9d420326979fed4a065fa6176d5e09bd513cd2820fe216ae8b684aa6780d72b2",
+ build_file = "//third_party:honggfuzz.BUILD",
+ strip_prefix = "honggfuzz-1.7",
+)
+
+http_archive(
+ name = "benchmark",
+ url = "https://github.com/google/benchmark/archive/v1.4.1.zip",
+ sha256 = "61ae07eb5d4a0b02753419eb17a82b7d322786bb36ab62bd3df331a4d47c00a7",
+ strip_prefix = "benchmark-1.4.1",
+)
diff --git a/3rdparty/astc-codec/cmake-format.json b/3rdparty/astc-codec/cmake-format.json
new file mode 100644
index 0000000..de38ed2
--- /dev/null
+++ b/3rdparty/astc-codec/cmake-format.json
@@ -0,0 +1,38 @@
+{
+ "line_width": 120,
+ "dangle_parens": false,
+ "first_comment_is_literal": true,
+ "algorithm_order": [
+ 0,
+ 1,
+ 2,
+ 3
+ ],
+ "command_case": "lower",
+ "additional_commands": {
+ "foo": {
+ "flags": [
+ "BAR",
+ "BAZ"
+ ],
+ "kwargs": {
+ "HEADERS": "*",
+ "DEPENDS": "*",
+ "SOURCES": "*"
+ }
+ }
+ },
+ "separate_fn_name_with_space": false,
+ "always_wrap": [],
+ "separate_ctrl_name_with_space": false,
+ "max_subargs_per_line": 5,
+ "fence_pattern": "^\\s*([`~]{3}[`~]*)(.*)$",
+ "enable_markup": true,
+ "ruler_pattern": "^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$",
+ "tab_size": 2,
+ "keyword_case": "unchanged",
+ "enum_char": ".",
+ "literal_comment_pattern": null,
+ "bullet_char": "*",
+ "line_ending": "unix"
+}
diff --git a/3rdparty/astc-codec/include/astc-codec/astc-codec.h b/3rdparty/astc-codec/include/astc-codec/astc-codec.h
new file mode 100644
index 0000000..1d41218
--- /dev/null
+++ b/3rdparty/astc-codec/include/astc-codec/astc-codec.h
@@ -0,0 +1,75 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ASTC_CODEC_ASTC_CODEC_H_
+#define ASTC_CODEC_ASTC_CODEC_H_
+
+#include
+#include
+
+namespace astc_codec {
+
+// These are the valid ASTC footprints according to the specification in
+// Section C.2.7.
+enum class FootprintType {
+ k4x4,
+ k5x4,
+ k5x5,
+ k6x5,
+ k6x6,
+ k8x5,
+ k8x6,
+ k10x5,
+ k10x6,
+ k8x8,
+ k10x8,
+ k10x10,
+ k12x10,
+ k12x12,
+
+ kCount
+};
+
+// Decompresses ASTC LDR image data to a RGBA32 buffer.
+//
+// Supports formats defined in the KHR_texture_compression_astc_ldr spec and
+// returns UNORM8 values. sRGB is not supported, and should be implemented
+// by the caller.
+//
+// |astc_data| - Compressed ASTC image buffer, must be at least |astc_data_size|
+// bytes long.
+// |astc_data_size| - The size of |astc_data|, in bytes.
+// |width| - Image width, in pixels.
+// |height| - Image height, in pixels.
+// |footprint| - The ASTC footprint (block size) of the compressed image buffer.
+// |out_buffer| - Pointer to a buffer where the decompressed image will be
+// stored, must be at least |out_buffer_size| bytes long.
+// |out_buffer_size| - The size of |out_buffer|, in bytes, at least
+// height*out_buffer_stride. If this is too small, this
+// function will return false and no data will be
+// decompressed.
+// |out_buffer_stride| - The stride that should be used to store rows of the
+// decoded image, must be at least 4*width bytes.
+//
+// Returns true if the decompression succeeded, or false if decompression
+// failed, or if the astc_data_size was too small for the given width, height,
+// and footprint, or if out_buffer_size is too small.
+bool ASTCDecompressToRGBA(const uint8_t* astc_data, size_t astc_data_size,
+ size_t width, size_t height, FootprintType footprint,
+ uint8_t* out_buffer, size_t out_buffer_size,
+ size_t out_buffer_stride);
+
+} // namespace astc_codec
+
+#endif // ASTC_CODEC_ASTC_CODEC_H_
diff --git a/3rdparty/astc-codec/src/.clang-format b/3rdparty/astc-codec/src/.clang-format
new file mode 100644
index 0000000..9a00ee2
--- /dev/null
+++ b/3rdparty/astc-codec/src/.clang-format
@@ -0,0 +1,4 @@
+BasedOnStyle: Google
+AllowShortCaseLabelsOnASingleLine: true
+AllowShortFunctionsOnASingleLine: Inline
+SpaceAfterTemplateKeyword: false
diff --git a/3rdparty/astc-codec/src/base/BUILD.bazel b/3rdparty/astc-codec/src/base/BUILD.bazel
new file mode 100644
index 0000000..84d2131
--- /dev/null
+++ b/3rdparty/astc-codec/src/base/BUILD.bazel
@@ -0,0 +1,49 @@
+# Copyright 2018 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+licenses(["notice"])
+
+cc_library(
+ name = "base",
+ hdrs = [
+ "bit_stream.h",
+ "bottom_n.h",
+ "math_utils.h",
+ "optional.h",
+ "string_utils.h",
+ "type_traits.h",
+ "uint128.h",
+ "utils.h",
+ ],
+ features = ["-parse_headers"],
+ visibility = ["//src/decoder:__pkg__"],
+)
+
+cc_test(
+ name = "base_test",
+ srcs = [
+ "test/bit_stream_test.cpp",
+ "test/bottom_n_test.cpp",
+ "test/math_utils_test.cpp",
+ "test/optional_test.cpp",
+ "test/string_utils_test.cpp",
+ "test/type_traits_test.cpp",
+ "test/uint128_test.cpp",
+ ],
+ deps = [
+ "@gtest//:gtest_main",
+ ":base",
+ ],
+)
+
diff --git a/3rdparty/astc-codec/src/base/CMakeLists.txt b/3rdparty/astc-codec/src/base/CMakeLists.txt
new file mode 100644
index 0000000..5a45f85
--- /dev/null
+++ b/3rdparty/astc-codec/src/base/CMakeLists.txt
@@ -0,0 +1,27 @@
+# Copyright 2018 Google LLC
+#
+# Licensed under the Apache License Version 2.0 (the License); you may not use
+# this file except in compliance with the License. You may obtain a copy of the
+# License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing software distributed
+# under the License is distributed on an AS IS BASIS WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND either express or implied. See the License for the
+# specific language governing permissions and limitations under the License.
+add_library(base INTERFACE)
+target_include_directories(base INTERFACE ../..)
+
+if(OPTION_ASTC_TESTS)
+ add_executable(base_test
+ test/bit_stream_test.cpp
+ test/bottom_n_test.cpp
+ test/math_utils_test.cpp
+ test/optional_test.cpp
+ test/string_utils_test.cpp
+ test/type_traits_test.cpp
+ test/uint128_test.cpp)
+ target_link_libraries(base_test base gmock_main)
+ add_test(NAME base_test COMMAND base_test WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
+endif()
diff --git a/3rdparty/astc-codec/src/base/bit_stream.h b/3rdparty/astc-codec/src/base/bit_stream.h
new file mode 100644
index 0000000..2cda093
--- /dev/null
+++ b/3rdparty/astc-codec/src/base/bit_stream.h
@@ -0,0 +1,77 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ASTC_CODEC_BASE_BIT_STREAM_H_
+#define ASTC_CODEC_BASE_BIT_STREAM_H_
+
+#include
+#include
+
+namespace astc_codec {
+namespace base {
+
+// Represents a stream of bits that can be read or written in arbitrary-sized
+// chunks.
+template
+class BitStream {
+ public:
+ // Creates an empty BitStream.
+ BitStream() = default;
+ BitStream(IntType data, uint32_t data_size)
+ : data_(data), data_size_(data_size) {
+ assert(data_size_ <= sizeof(data_) * 8);
+ }
+
+ // Return the number of bits in the stream.
+ uint32_t Bits() const { return data_size_; }
+
+ // Put |size| bits into the stream.
+ // Fails if there is not enough space in the buffer to store the bits.
+ template
+ void PutBits(ResultType x, uint32_t size) {
+ assert(data_size_ + size <= sizeof(data_) * 8);
+
+ data_ |= (IntType(x) & MaskFor(size)) << data_size_;
+ data_size_ += size;
+ }
+
+ // Get |count| bits from the stream.
+ // Returns true if |count| bits were successfully retrieved.
+ template
+ bool GetBits(uint32_t count, ResultType* result) {
+ if (count <= data_size_) {
+ *result = static_cast(data_ & MaskFor(count));
+ data_ = data_ >> count;
+ data_size_ -= count;
+ return true;
+ } else {
+ *result = ResultType();
+ return false;
+ }
+ }
+
+ private:
+ IntType MaskFor(uint32_t bits) const {
+ return (bits == sizeof(IntType) * 8) ? ~IntType(0)
+ : (IntType(1) << bits) - 1;
+ }
+
+ IntType data_ = IntType();
+ uint32_t data_size_ = 0;
+};
+
+} // namespace base
+} // namespace astc_codec
+
+#endif // ASTC_CODEC_BASE_BIT_STREAM_H_
diff --git a/3rdparty/astc-codec/src/base/bottom_n.h b/3rdparty/astc-codec/src/base/bottom_n.h
new file mode 100644
index 0000000..4edc8ef
--- /dev/null
+++ b/3rdparty/astc-codec/src/base/bottom_n.h
@@ -0,0 +1,78 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ASTC_CODEC_BASE_BOTTOM_N_H_
+#define ASTC_CODEC_BASE_BOTTOM_N_H_
+
+#include
+#include
+#include
+
+namespace astc_codec {
+namespace base {
+
+// Used to aggregate the lowest N values of data supplied.
+template>
+class BottomN {
+ public:
+ typedef std::vector ContainerType;
+
+ // Creates an empty BottomN with limit |max_size|.
+ BottomN(size_t max_size) : max_size_(max_size) { }
+
+ bool Empty() const { return data_.empty(); }
+ size_t Size() const { return data_.size(); }
+
+ const T& Top() const { return data_.front(); }
+
+ void Push(const T& value) {
+ if (data_.size() < max_size_ || compare_(value, Top())) {
+ data_.push_back(value);
+ std::push_heap(data_.begin(), data_.end(), compare_);
+
+ if (Size() > max_size_) {
+ PopTop();
+ }
+ }
+ }
+
+ std::vector Pop() {
+ const size_t len = Size();
+ std::vector result(len);
+
+ for (size_t i = 0; i < len; ++i) {
+ result[len - i - 1] = PopTop();
+ }
+
+ return result;
+ }
+
+ private:
+ T PopTop() {
+ std::pop_heap(data_.begin(), data_.end(), compare_);
+ T result = data_.back();
+ data_.pop_back();
+ return result;
+ }
+
+ ContainerType data_;
+ CompareFn compare_;
+
+ const size_t max_size_;
+};
+
+} // namespace base
+} // namespace astc_codec
+
+#endif // ASTC_CODEC_BASE_BOTTOM_N_H_
diff --git a/3rdparty/astc-codec/src/base/math_utils.h b/3rdparty/astc-codec/src/base/math_utils.h
new file mode 100644
index 0000000..48f1a24
--- /dev/null
+++ b/3rdparty/astc-codec/src/base/math_utils.h
@@ -0,0 +1,80 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ASTC_CODEC_BASE_MATH_UTILS_H_
+#define ASTC_CODEC_BASE_MATH_UTILS_H_
+
+#include "src/base/uint128.h"
+
+#include
+#include
+#include
+
+namespace astc_codec {
+namespace base {
+
+inline int Log2Floor(uint32_t n) {
+ if (n == 0) {
+ return -1;
+ }
+
+ int log = 0;
+ uint32_t value = n;
+ for (int i = 4; i >= 0; --i) {
+ int shift = (1 << i);
+ uint32_t x = value >> shift;
+ if (x != 0) {
+ value = x;
+ log += shift;
+ }
+ }
+ assert(value == 1);
+ return log;
+}
+
+inline int CountOnes(uint32_t n) {
+ n -= ((n >> 1) & 0x55555555);
+ n = ((n >> 2) & 0x33333333) + (n & 0x33333333);
+ return static_cast((((n + (n >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24);
+}
+
+template
+inline T ReverseBits(T value) {
+ uint32_t s = sizeof(value) * 8;
+ T mask = ~T(0);
+ while ((s >>= 1) > 0) {
+ mask ^= (mask << s);
+ value = ((value >> s) & mask) | ((value << s) & ~mask);
+ }
+
+ return value;
+}
+
+template
+inline T GetBits(T source, uint32_t offset, uint32_t count) {
+ static_assert(std::is_same::value || std::is_unsigned::value,
+ "T must be unsigned.");
+
+ const uint32_t total_bits = sizeof(T) * 8;
+ assert(count > 0);
+ assert(offset + count <= total_bits);
+
+ const T mask = count == total_bits ? ~T(0) : ~T(0) >> (total_bits - count);
+ return (source >> offset) & mask;
+}
+
+} // namespace base
+} // namespace astc_codec
+
+#endif // ASTC_CODEC_BASE_MATH_UTILS_H_
diff --git a/3rdparty/astc-codec/src/base/optional.h b/3rdparty/astc-codec/src/base/optional.h
new file mode 100644
index 0000000..5ede4af
--- /dev/null
+++ b/3rdparty/astc-codec/src/base/optional.h
@@ -0,0 +1,520 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ASTC_CODEC_BASE_OPTIONAL_H_
+#define ASTC_CODEC_BASE_OPTIONAL_H_
+
+#include "src/base/type_traits.h"
+
+#include
+#include
+#include
+#include
+
+#include
+
+// Optional - a template class to store an optional value of type T.
+//
+// Usage examples:
+//
+// Initialization and construction:
+// Optional foo; // |foo| doesn't contain a value.
+// Optional foo(Foo(10)); // |foo| contains a copy-constructed value.
+// Optional foo2(foo); // |foo2| contains a copy of |foo|'s value.
+// Optional foo3(std::move(foo2)); // Guess what?
+//
+// Assignment:
+// Foo foo_value(0);
+// Optional foo; // |foo| is empty.
+// Optional foo2; // |foo2| is empty.
+// foo2 = foo; // |foo2| is still empty.
+// foo = foo_value; // set value of |foo| to a copy of |foo_value|
+// foo = std::move(foo_value); // move |foo_value| into |foo|.
+// foo2 = foo; // now |foo2| has a copy of |foo|'s value.
+// foo = kNullopt; // unset |foo|, it has no value.
+//
+// Checking and accessing value:
+// if (foo) {
+// // |foo| has a value.
+// doStuff(*foo); // |*foo| is the value inside |foo|.
+// foo->callMethod(); // Same as (*foo).callMethod().
+// } else {
+// // |foo| is empty.
+// }
+//
+// foo.value() // Same as *foo
+// foo.valueOr() // Return is |foo| has no value.
+//
+// In-place construction:
+//
+// Optional foo; // |foo| is empty.
+// foo.emplace(20); // |foo| now contains a value constructed as Foo(20)
+//
+// Optional foo(kInplace, 20); // |foo| is initialized with a value
+// // that is constructed in-place as
+// // Foo(20).
+//
+// return makeOptional(20); // Takes Foo constructor arguments
+// // directly.
+//
+// Returning values:
+//
+// Optional myFunc(...) {
+// if (someCondition) {
+// return Foo(10); // call Optional(Foo&) constructor.
+// } else {
+// return {}; // call Optional() constructor, which
+// // builds an empty value.
+// }
+// }
+//
+// Memory layout:
+// Optional is equivalent to:
+//
+// struct {
+// bool flag;
+// Foo value;
+// };
+//
+// in terms of memory layout. This means it *doubles* the size of integral
+// types. Also:
+//
+// - Optional can be constructed from anything that constructs a Foo.
+//
+// - Same with Optional(kInplace, Args...) where Args... matches any
+// arguments that can be passed to a Foo constructor.
+//
+// - Comparison operators are provided. Beware: an empty Optional
+// is always smaller than any Foo value.
+
+namespace astc_codec {
+namespace base {
+
+namespace details {
+
+// Base classes to reduce the number of instantiations of the Optional's
+// internal members.
+class OptionalFlagBase {
+ public:
+ void setConstructed(bool constructed) { mConstructed = constructed; }
+ constexpr bool constructed() const { return mConstructed; }
+ constexpr operator bool() const { return constructed(); }
+ bool hasValue() const { return constructed(); }
+
+ constexpr OptionalFlagBase(bool constructed = false)
+ : mConstructed(constructed) { }
+
+ private:
+ bool mConstructed = false;
+};
+
+template
+class OptionalStorageBase {
+ protected:
+ using StoreT = typename std::aligned_storage::type;
+ StoreT mStorage = {};
+};
+
+} // namespace details
+
+// A tag type for empty optional construction
+struct NulloptT {
+ constexpr explicit NulloptT(int) { }
+};
+
+// A tag type for inplace value construction
+struct InplaceT {
+ constexpr explicit InplaceT(int) { }
+};
+
+// Tag values for null optional and inplace construction
+constexpr NulloptT kNullopt{1};
+constexpr InplaceT kInplace{1};
+
+// Forward declaration for an early use
+template
+class Optional;
+
+// A type trait for checking if a type is an optional instantiation
+// Note: if you want to refer to the template name inside the template,
+// you need to declare this alias outside of it - because the
+// class name inside of the template stands for an instantiated template
+// E.g, for template class Foo if you say 'Foo' inside the class, it
+// actually means Foo;
+template
+using is_any_optional =
+ is_template_instantiation_of::type, Optional>;
+
+template
+class Optional
+ : private details::OptionalFlagBase,
+ private details::OptionalStorageBase::value> {
+ // make sure all optionals are buddies - this is needed to implement
+ // conversion from optionals of other types
+ template
+ friend class Optional;
+
+ template
+ using self = Optional;
+
+ using base_flag = details::OptionalFlagBase;
+ using base_storage =
+ details::OptionalStorageBase::value>;
+
+ public:
+ // std::optional will have this, so let's provide it
+ using value_type = T;
+
+ // make sure we forbid some Optional instantiations where things may get
+ // really messy
+ static_assert(!std::is_same::type, NulloptT>::value,
+ "Optional of NulloptT is not allowed");
+ static_assert(!std::is_same::type, InplaceT>::value,
+ "Optional of InplaceT is not allowed");
+ static_assert(!std::is_reference::value,
+ "Optional references are not allowed: use a pointer instead");
+
+ // constructors
+ constexpr Optional() { }
+ constexpr Optional(NulloptT) { }
+
+ Optional(const Optional& other) : base_flag(other.constructed()) {
+ if (this->constructed()) {
+ new (&get()) T(other.get());
+ }
+ }
+ Optional(Optional&& other) : base_flag(other.constructed()) {
+ if (this->constructed()) {
+ new (&get()) T(std::move(other.get()));
+ }
+ }
+
+ // Conversion constructor from optional of similar type
+ template::value &&
+ std::is_constructible::value>>
+ Optional(const Optional& other) : base_flag(other.constructed()) {
+ if (this->constructed()) {
+ new (&get()) T(other.get());
+ }
+ }
+
+ // Move-conversion constructor
+ template::value &&
+ std::is_constructible::value>>
+ Optional(Optional&& other) : base_flag(other.constructed()) {
+ if (this->constructed()) {
+ new (&get()) T(std::move(other.get()));
+ }
+ }
+
+ // Construction from a raw value
+ Optional(const T& value) : base_flag(true) { new (&get()) T(value); }
+ // Move construction from a raw value
+ Optional(T&& value) : base_flag(true) { new (&get()) T(std::move(value)); }
+
+ // Inplace construction from a list of |T|'s ctor arguments
+ template
+ Optional(InplaceT, Args&&... args) : base_flag(true) {
+ new (&get()) T(std::forward(args)...);
+ }
+
+ // Inplace construction from an initializer list passed into |T|'s ctor
+ template>>>
+ Optional(InplaceT, std::initializer_list il) : base_flag(true) {
+ new (&get()) T(il);
+ }
+
+ // direct assignment
+ Optional& operator=(const Optional& other) {
+ if (&other == this) {
+ return *this;
+ }
+
+ if (this->constructed()) {
+ if (other.constructed()) {
+ get() = other.get();
+ } else {
+ destruct();
+ this->setConstructed(false);
+ }
+ } else {
+ if (other.constructed()) {
+ new (&get()) T(other.get());
+ this->setConstructed(true);
+ } else {
+ ; // we're good
+ }
+ }
+ return *this;
+ }
+
+ // move assignment
+ Optional& operator=(Optional&& other) {
+ if (this->constructed()) {
+ if (other.constructed()) {
+ get() = std::move(other.get());
+ } else {
+ destruct();
+ this->setConstructed(false);
+ }
+ } else {
+ if (other.constructed()) {
+ new (&get()) T(std::move(other.get()));
+ this->setConstructed(true);
+ } else {
+ ; // we're good
+ }
+ }
+ return *this;
+ }
+
+ // conversion assignment
+ template::type, T>>
+ Optional& operator=(const Optional& other) {
+ if (this->constructed()) {
+ if (other.constructed()) {
+ get() = other.get();
+ } else {
+ destruct();
+ this->setConstructed(false);
+ }
+ } else {
+ if (other.constructed()) {
+ new (&get()) T(other.get());
+ this->setConstructed(true);
+ } else {
+ ; // we're good
+ }
+ }
+ return *this;
+ }
+
+ // conversion move assignment
+ template::type, T>>
+ Optional& operator=(Optional&& other) {
+ if (this->constructed()) {
+ if (other.constructed()) {
+ get() = std::move(other.get());
+ } else {
+ destruct();
+ this->setConstructed(false);
+ }
+ } else {
+ if (other.constructed()) {
+ new (&get()) T(std::move(other.get()));
+ this->setConstructed(true);
+ } else {
+ ; // we're good
+ }
+ }
+ return *this;
+ }
+
+ // the most complicated one: forwarding constructor for anything convertible
+ // to |T|, excluding the stuff implemented above explicitly
+ template::type>::value &&
+ std::is_convertible::type, T>::value>>
+ Optional& operator=(U&& other) {
+ if (this->constructed()) {
+ get() = std::forward(other);
+ } else {
+ new (&get()) T(std::forward(other));
+ this->setConstructed(true);
+ }
+ return *this;
+ }
+
+ // Adopt value checkers from the parent
+ using base_flag::operator bool;
+ using base_flag::hasValue;
+
+ T& value() {
+ assert(this->constructed());
+ return get();
+ }
+ constexpr const T& value() const {
+ assert(this->constructed());
+ return get();
+ }
+
+ T* ptr() { return this->constructed() ? &get() : nullptr; }
+ constexpr const T* ptr() const {
+ return this->constructed() ? &get() : nullptr;
+ }
+
+ // Value getter with fallback
+ template::type, T>>
+ constexpr T valueOr(U&& defaultValue) const {
+ return this->constructed() ? get() : std::move(defaultValue);
+ }
+
+ // Pointer-like operators
+ T& operator*() {
+ assert(this->constructed());
+ return get();
+ }
+ constexpr const T& operator*() const {
+ assert(this->constructed());
+ return get();
+ }
+
+ T* operator->() {
+ assert(this->constructed());
+ return &get();
+ }
+ constexpr const T* operator->() const {
+ assert(this->constructed());
+ return &get();
+ }
+
+ ~Optional() {
+ if (this->constructed()) {
+ destruct();
+ }
+ }
+
+ void clear() {
+ if (this->constructed()) {
+ destruct();
+ this->setConstructed(false);
+ }
+ }
+
+ template::type, T>>
+ void reset(U&& u) {
+ *this = std::forward(u);
+ }
+
+ // In-place construction with possible destruction of the old value
+ template
+ void emplace(Args&&... args) {
+ if (this->constructed()) {
+ destruct();
+ }
+ new (&get()) T(std::forward(args)...);
+ this->setConstructed(true);
+ }
+
+ // In-place construction with possible destruction of the old value
+ // initializer-list version
+ template>>>
+ void emplace(std::initializer_list il) {
+ if (this->constructed()) {
+ destruct();
+ }
+ new (&get()) T(il);
+ this->setConstructed(true);
+ }
+
+ private:
+ // A helper function to convert the internal raw storage to T&
+ constexpr const T& get() const {
+ return *reinterpret_cast(
+ reinterpret_cast(&this->mStorage));
+ }
+
+ // Same thing, mutable
+ T& get() { return const_cast(const_cast(this)->get()); }
+
+ // Shortcut for a destructor call for the stored object
+ void destruct() { get().T::~T(); }
+};
+
+template
+Optional::type> makeOptional(T&& t) {
+ return Optional::type>(std::forward(t));
+}
+
+template
+Optional::type> makeOptional(Args&&... args) {
+ return Optional::type>(kInplace,
+ std::forward(args)...);
+}
+
+template
+bool operator==(const Optional& l, const Optional& r) {
+ return l.hasValue() ? r.hasValue() && *l == *r : !r.hasValue();
+}
+template
+bool operator==(const Optional& l, NulloptT) {
+ return !l;
+}
+template
+bool operator==(NulloptT, const Optional& r) {
+ return !r;
+}
+template
+bool operator==(const Optional& l, const T& r) {
+ return bool(l) && *l == r;
+}
+template
+bool operator==(const T& l, const Optional& r) {
+ return bool(r) && l == *r;
+}
+
+template
+bool operator!=(const Optional& l, const Optional& r) {
+ return !(l == r);
+}
+template
+bool operator!=(const Optional& l, NulloptT) {
+ return bool(l);
+}
+template
+bool operator!=(NulloptT, const Optional& r) {
+ return bool(r);
+}
+template
+bool operator!=(const Optional& l, const T& r) {
+ return !l || !(*l == r);
+}
+template
+bool operator!=(const T& l, const Optional& r) {
+ return !r || !(l == *r);
+}
+
+template
+bool operator<(const Optional& l, const Optional& r) {
+ return !r ? false : (!l ? true : *l < *r);
+}
+template
+bool operator<(const Optional&, NulloptT) {
+ return false;
+}
+template
+bool operator<(NulloptT, const Optional& r) {
+ return bool(r);
+}
+template
+bool operator<(const Optional& l, const T& r) {
+ return !l || *l < r;
+}
+template
+bool operator<(const T& l, const Optional& r) {
+ return bool(r) && l < *r;
+}
+
+} // namespace base
+} // namespace astc_codec
+
+#endif // ASTC_CODEC_BASE_OPTIONAL_H_
diff --git a/3rdparty/astc-codec/src/base/string_utils.h b/3rdparty/astc-codec/src/base/string_utils.h
new file mode 100644
index 0000000..c450b27
--- /dev/null
+++ b/3rdparty/astc-codec/src/base/string_utils.h
@@ -0,0 +1,68 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ASTC_CODEC_BASE_STRING_UTILS_H_
+#define ASTC_CODEC_BASE_STRING_UTILS_H_
+
+#include
+#include
+
+namespace astc_codec {
+namespace base {
+
+// Iterates over a string's parts using |splitBy| as a delimiter.
+// |splitBy| must be a nonempty string well, or it's a no-op.
+// Otherwise, |func| is called on each of the splits, excluding the
+// characters that are part of |splitBy|. If two |splitBy|'s occur in a row,
+// |func| will be called on a StringView("") in between. See
+// StringUtils_unittest.cpp for the full story.
+template
+void Split(const std::string& str, const std::string& splitBy, Func func) {
+ if (splitBy.empty()) {
+ return;
+ }
+
+ size_t splitSize = splitBy.size();
+ size_t begin = 0;
+ size_t end = str.find(splitBy);
+
+ while (true) {
+ func(str.substr(begin, end - begin));
+ if (end == std::string::npos) {
+ return;
+ }
+
+ begin = end + splitSize;
+ end = str.find(splitBy, begin);
+ }
+}
+
+static int32_t ParseInt32(const char* str, int32_t deflt) {
+ using std::numeric_limits;
+
+ char* error = nullptr;
+ int64_t value = strtol(str, &error, 0);
+ // Limit long values to int32 min/max. Needed for lp64; no-op on 32 bits.
+ if (value > std::numeric_limits::max()) {
+ value = std::numeric_limits::max();
+ } else if (value < std::numeric_limits::min()) {
+ value = std::numeric_limits::min();
+ }
+ return (error == str) ? deflt : static_cast(value);
+}
+
+} // namespace base
+} // namespace astc_codec
+
+#endif // ASTC_CODEC_BASE_STRING_UTILS_H_
diff --git a/3rdparty/astc-codec/src/base/test/bit_stream_test.cpp b/3rdparty/astc-codec/src/base/test/bit_stream_test.cpp
new file mode 100644
index 0000000..0c4b3c9
--- /dev/null
+++ b/3rdparty/astc-codec/src/base/test/bit_stream_test.cpp
@@ -0,0 +1,141 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/base/bit_stream.h"
+
+#include
+
+namespace astc_codec {
+namespace base {
+
+namespace {
+ static constexpr uint64_t kAllBits = 0xFFFFFFFFFFFFFFFF;
+ static constexpr uint64_t k40Bits = 0x000000FFFFFFFFFF;
+}
+
+TEST(BitStream, Decode) {
+ {
+ BitStream stream(0, 1);
+
+ uint64_t bits = kAllBits;
+ EXPECT_TRUE(stream.GetBits(1, &bits));
+ EXPECT_EQ(bits, 0);
+ EXPECT_FALSE(stream.GetBits(1, &bits));
+ }
+
+ {
+ BitStream stream(0b1010101010101010, 32);
+ EXPECT_EQ(stream.Bits(), 32);
+
+ uint64_t bits = 0;
+ EXPECT_TRUE(stream.GetBits(1, &bits));
+ EXPECT_EQ(bits, 0);
+
+ EXPECT_TRUE(stream.GetBits(3, &bits));
+ EXPECT_EQ(bits, 0b101);
+
+ EXPECT_TRUE(stream.GetBits(8, &bits));
+ EXPECT_EQ(bits, 0b10101010);
+
+ EXPECT_EQ(stream.Bits(), 20);
+
+ EXPECT_TRUE(stream.GetBits(20, &bits));
+ EXPECT_EQ(bits, 0b1010);
+ EXPECT_EQ(stream.Bits(), 0);
+ }
+
+ {
+ BitStream stream(kAllBits, 64);
+ EXPECT_EQ(stream.Bits(), 64);
+
+ uint64_t bits = 0;
+ EXPECT_TRUE(stream.GetBits(64, &bits));
+ EXPECT_EQ(bits, kAllBits);
+ EXPECT_EQ(stream.Bits(), 0);
+ }
+
+ {
+ BitStream stream(kAllBits, 64);
+ EXPECT_EQ(stream.Bits(), 64);
+
+ uint64_t bits = 0;
+ EXPECT_TRUE(stream.GetBits(40, &bits));
+ EXPECT_EQ(bits, k40Bits);
+ EXPECT_EQ(stream.Bits(), 24);
+ }
+
+ {
+ BitStream stream(kAllBits, 32);
+
+ uint64_t bits = 0;
+ EXPECT_TRUE(stream.GetBits(0, &bits));
+ EXPECT_EQ(bits, 0);
+ EXPECT_TRUE(stream.GetBits(32, &bits));
+ EXPECT_EQ(bits, k40Bits & 0xFFFFFFFF);
+ EXPECT_TRUE(stream.GetBits(0, &bits));
+ EXPECT_EQ(bits, 0);
+ EXPECT_EQ(stream.Bits(), 0);
+ }
+}
+
+TEST(BitStream, Encode) {
+ {
+ BitStream stream;
+
+ stream.PutBits(0, 1);
+ stream.PutBits(0b11, 2);
+ EXPECT_EQ(stream.Bits(), 3);
+
+ uint64_t bits = 0;
+ EXPECT_TRUE(stream.GetBits(3, &bits));
+ EXPECT_EQ(bits, 0b110);
+ }
+
+ {
+ BitStream stream;
+
+ uint64_t bits = 0;
+ stream.PutBits(kAllBits, 64);
+ EXPECT_EQ(stream.Bits(), 64);
+
+ EXPECT_TRUE(stream.GetBits(64, &bits));
+ EXPECT_EQ(bits, kAllBits);
+ EXPECT_EQ(stream.Bits(), 0);
+ }
+
+ {
+ BitStream stream;
+ stream.PutBits(kAllBits, 40);
+
+ uint64_t bits = 0;
+ EXPECT_TRUE(stream.GetBits(40, &bits));
+ EXPECT_EQ(bits, k40Bits);
+ EXPECT_EQ(stream.Bits(), 0);
+ }
+
+ {
+ BitStream stream;
+ stream.PutBits(0, 0);
+ stream.PutBits(kAllBits, 32);
+ stream.PutBits(0, 0);
+
+ uint64_t bits = 0;
+ EXPECT_TRUE(stream.GetBits(32, &bits));
+ EXPECT_EQ(bits, k40Bits & 0xFFFFFFFF);
+ EXPECT_EQ(stream.Bits(), 0);
+ }
+}
+
+} // namespace base
+} // namespace astc_codec
diff --git a/3rdparty/astc-codec/src/base/test/bottom_n_test.cpp b/3rdparty/astc-codec/src/base/test/bottom_n_test.cpp
new file mode 100644
index 0000000..71265d7
--- /dev/null
+++ b/3rdparty/astc-codec/src/base/test/bottom_n_test.cpp
@@ -0,0 +1,108 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/base/bottom_n.h"
+
+#include
+#include
+
+namespace astc_codec {
+namespace base {
+
+using ::testing::ElementsAre;
+
+template
+static void pushAll(BottomN& heap, const T (&arr)[N]) {
+ for (auto i : arr) {
+ heap.Push(i);
+ }
+}
+
+TEST(BottomN, Sort) {
+ {
+ BottomN heap(10);
+ EXPECT_TRUE(heap.Empty());
+ int list[] = { 1,2 };
+ pushAll(heap, list);
+
+ EXPECT_EQ(heap.Size(), 2);
+ EXPECT_FALSE(heap.Empty());
+ EXPECT_THAT(heap.Pop(), ElementsAre(1, 2));
+ }
+
+ {
+ BottomN heap(6);
+ int list[] = {1, 4, 3, 2, 2, 1};
+ pushAll(heap, list);
+
+ EXPECT_EQ(heap.Size(), 6);
+ EXPECT_THAT(heap.Pop(), ElementsAre(1, 1, 2, 2, 3, 4));
+ }
+}
+
+TEST(BottomN, Bounds) {
+ {
+ BottomN heap(4);
+ int list[] = { 1, 2, 3, 4 };
+ pushAll(heap, list);
+ EXPECT_EQ(heap.Size(), 4);
+
+ heap.Push(0);
+ EXPECT_EQ(heap.Size(), 4);
+
+ EXPECT_THAT(heap.Pop(), ElementsAre(0, 1, 2, 3));
+ }
+
+ {
+ BottomN heap(4);
+ int list[] = { 4, 3, 2,1 };
+ pushAll(heap, list);
+ EXPECT_EQ(heap.Size(), 4);
+
+ int list2[] = { 4,4,4,4 };
+ pushAll(heap, list2);
+ EXPECT_EQ(heap.Size(), 4);
+
+ EXPECT_THAT(heap.Pop(), ElementsAre(1, 2, 3, 4));
+ }
+
+ {
+ BottomN heap(4);
+ int list[] = { 4, 3, 2, 1 };
+ pushAll(heap, list);
+ EXPECT_EQ(heap.Size(), 4);
+
+ int list2[] = { 5, 5, 5, 5 };
+ pushAll(heap, list2);
+ EXPECT_EQ(heap.Size(), 4);
+
+ EXPECT_THAT(heap.Pop(), ElementsAre(1, 2, 3, 4));
+ }
+
+ {
+ BottomN heap(4);
+ int list[] = { 4, 3, 2, 1 };
+ pushAll(heap, list);
+ EXPECT_EQ(heap.Size(), 4);
+
+ int list2[] = { 0, 0, 0, 0 };
+ pushAll(heap, list2);
+ EXPECT_EQ(heap.Size(), 4);
+
+ EXPECT_THAT(heap.Pop(), ElementsAre(0, 0, 0, 0));
+ }
+}
+
+} // namespace base
+} // namespace astc_codec
diff --git a/3rdparty/astc-codec/src/base/test/math_utils_test.cpp b/3rdparty/astc-codec/src/base/test/math_utils_test.cpp
new file mode 100644
index 0000000..0371e11
--- /dev/null
+++ b/3rdparty/astc-codec/src/base/test/math_utils_test.cpp
@@ -0,0 +1,78 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/base/math_utils.h"
+
+#include
+
+namespace astc_codec {
+namespace base {
+
+TEST(MathUtils, Log2Floor) {
+ EXPECT_EQ(-1, Log2Floor(0));
+
+ for (int i = 0; i < 32; i++) {
+ uint32_t n = 1U << i;
+ EXPECT_EQ(i, Log2Floor(n));
+ if (n > 2) {
+ EXPECT_EQ(i - 1, Log2Floor(n - 1));
+ EXPECT_EQ(i, Log2Floor(n + 1));
+ }
+ }
+}
+
+TEST(MathUtils, CountOnes) {
+ EXPECT_EQ(0, CountOnes(0));
+ EXPECT_EQ(1, CountOnes(1));
+ EXPECT_EQ(32, CountOnes(static_cast(~0U)));
+ EXPECT_EQ(1, CountOnes(0x8000000));
+
+ for (int i = 0; i < 32; i++) {
+ EXPECT_EQ(1, CountOnes(1U << i));
+ EXPECT_EQ(31, CountOnes(static_cast(~0U) ^ (1U << i)));
+ }
+}
+
+TEST(MathUtils, ReverseBits) {
+ EXPECT_EQ(ReverseBits(0u), 0u);
+ EXPECT_EQ(ReverseBits(1u), 1u << 31);
+ EXPECT_EQ(ReverseBits(0xffffffff), 0xffffffff);
+ EXPECT_EQ(ReverseBits(0x00000001), 0x80000000);
+ EXPECT_EQ(ReverseBits(0x80000000), 0x00000001);
+ EXPECT_EQ(ReverseBits(0xaaaaaaaa), 0x55555555);
+ EXPECT_EQ(ReverseBits(0x55555555), 0xaaaaaaaa);
+ EXPECT_EQ(ReverseBits(0x7d5d7f53), 0xcafebabe);
+ EXPECT_EQ(ReverseBits(0xcafebabe), 0x7d5d7f53);
+}
+
+TEST(MathUtils, GetBits) {
+ EXPECT_EQ(GetBits(0u, 0, 1), 0u);
+ EXPECT_EQ(GetBits(0u, 0, 32), 0u);
+ EXPECT_EQ(GetBits(0x00000001u, 0, 1), 0x00000001);
+ EXPECT_EQ(GetBits(0x00000001u, 0, 32), 0x00000001);
+ EXPECT_EQ(GetBits(0x00000001u, 1, 31), 0x00000000);
+ EXPECT_EQ(GetBits(0x00000001u, 31, 1), 0x00000000);
+
+ EXPECT_DEBUG_DEATH(GetBits(0x00000000u, 1, 32), "");
+ EXPECT_DEBUG_DEATH(GetBits(0x00000000u, 32, 0), "");
+ EXPECT_DEBUG_DEATH(GetBits(0x00000000u, 32, 1), "");
+
+ EXPECT_EQ(GetBits(0XFFFFFFFFu, 0, 4), 0x0000000F);
+ EXPECT_EQ(GetBits(0XFFFFFFFFu, 16, 16), 0xFFFF);
+ EXPECT_EQ(GetBits(0x80000000u, 31, 1), 1);
+ EXPECT_EQ(GetBits(0xCAFEBABEu, 24, 8), 0xCA);
+}
+
+} // namespace base
+} // namespace astc_codec
diff --git a/3rdparty/astc-codec/src/base/test/optional_test.cpp b/3rdparty/astc-codec/src/base/test/optional_test.cpp
new file mode 100644
index 0000000..1eeefbd
--- /dev/null
+++ b/3rdparty/astc-codec/src/base/test/optional_test.cpp
@@ -0,0 +1,481 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/base/optional.h"
+
+#include
+
+#include
+#include
+
+namespace astc_codec {
+namespace base {
+
+TEST(Optional, TypeProperties) {
+ // Making sure optional has the correct alignment and doesn't waste too much
+ // space
+
+ static_assert(sizeof(Optional) == 2, "bad Optional size");
+ static_assert(std::alignment_of>::value ==
+ std::alignment_of::value,
+ "bad Optional alignment");
+
+ static_assert(sizeof(Optional) == 2, "bad Optional size");
+ static_assert(std::alignment_of>::value ==
+ std::alignment_of::value,
+ "bad Optional alignment");
+
+ static_assert(sizeof(Optional) == 4, "bad Optional size");
+ static_assert(std::alignment_of>::value ==
+ std::alignment_of::value,
+ "bad Optional alignment");
+
+ static_assert(sizeof(Optional) == 8, "bad Optional size");
+ static_assert(std::alignment_of>::value ==
+ std::alignment_of::value,
+ "bad Optional alignment");
+
+ static_assert(sizeof(Optional) == 16, "bad Optional size");
+ static_assert(std::alignment_of>::value ==
+ std::alignment_of::value,
+ "bad Optional alignment");
+
+ struct S128 {
+ int64_t data[2];
+ };
+
+ static_assert(sizeof(Optional) == 3 * sizeof(int64_t),
+ "bad Optional size");
+ static_assert(std::alignment_of>::value ==
+ std::alignment_of::value,
+ "bad Optional alignment");
+}
+
+TEST(Optional, ConstructFromValue) {
+ {
+ Optional o;
+ EXPECT_FALSE(o);
+ }
+ {
+ Optional o = {};
+ EXPECT_FALSE(o);
+ }
+ {
+ Optional o = kNullopt;
+ EXPECT_FALSE(o);
+ }
+ {
+ Optional o(1);
+ EXPECT_TRUE(o);
+ EXPECT_EQ(1, *o);
+ }
+ {
+ // check the std::decay<> constructor
+ Optional o = static_cast(1);
+ EXPECT_TRUE(o);
+ EXPECT_EQ(1, *o);
+ }
+ {
+ Optional o = 1;
+ EXPECT_TRUE(o);
+ EXPECT_EQ(1, *o);
+ }
+ {
+ Optional o{1};
+ EXPECT_TRUE(o);
+ EXPECT_EQ(1, *o);
+ }
+ {
+ short val = 10;
+ Optional o = val;
+ EXPECT_TRUE(o);
+ EXPECT_EQ(10, *o);
+ }
+ {
+ Optional> o(kInplace, 10);
+ EXPECT_TRUE(o);
+ EXPECT_EQ((std::vector(10)), *o);
+ }
+ {
+ Optional> o(kInplace, {1, 2, 3, 4});
+ EXPECT_TRUE(o);
+ EXPECT_EQ((std::vector{1, 2, 3, 4}), *o);
+ }
+}
+
+TEST(Optional, ConstructFromOptional) {
+ {
+ Optional o = Optional();
+ EXPECT_FALSE(o);
+ }
+ {
+ Optional o2;
+ Optional o(o2);
+ EXPECT_FALSE(o);
+ }
+ {
+ Optional o2 = 42;
+ Optional o(o2);
+ EXPECT_TRUE(o);
+ EXPECT_EQ(42, *o);
+ }
+ {
+ Optional o(Optional(1));
+ EXPECT_TRUE(o);
+ EXPECT_EQ(1, *o);
+ }
+ {
+ Optional o2 = 2;
+ Optional o = o2;
+ EXPECT_TRUE(o);
+ EXPECT_EQ(2, *o);
+ }
+ {
+ Optional> o2 = std::vector{20, 30, 40};
+ Optional> o = o2;
+ EXPECT_TRUE(o);
+ EXPECT_EQ((std::vector{20, 30, 40}), *o);
+ }
+}
+
+TEST(Optional, Assign) {
+ {
+ Optional o;
+ o = 1;
+ EXPECT_TRUE(o);
+ EXPECT_EQ(1, *o);
+
+ o = 2;
+ EXPECT_TRUE(o);
+ EXPECT_EQ(2, *o);
+
+ o = kNullopt;
+ EXPECT_FALSE(o);
+
+ o = Optional(10);
+ EXPECT_TRUE(o);
+ EXPECT_EQ(10, *o);
+
+ Optional o2;
+ o = o2;
+ EXPECT_FALSE(o);
+
+ o = 2u;
+ EXPECT_TRUE(o);
+ EXPECT_EQ(2, *o);
+
+ o = Optional();
+ EXPECT_FALSE(o);
+
+ o = Optional(20);
+ EXPECT_TRUE(o);
+ EXPECT_EQ(20, *o);
+
+ Optional o3(200);
+ o = o3;
+ EXPECT_TRUE(o);
+ EXPECT_EQ(200, *o);
+
+ o = {};
+ EXPECT_FALSE(o);
+
+ // check the std::decay<> assignment
+ o = static_cast(1);
+ EXPECT_TRUE(o);
+ EXPECT_EQ(1, *o);
+ }
+}
+
+TEST(Optional, MakeOptional) {
+ {
+ auto o = makeOptional(1);
+ static_assert(std::is_same>::value,
+ "Bad type deduction in makeOptional()");
+ EXPECT_TRUE(o);
+ EXPECT_EQ(1, *o);
+ }
+ {
+ auto o = makeOptional(std::vector{'1', '2'});
+ static_assert(std::is_same>>::value,
+ "Bad type deduction in makeOptional()");
+ EXPECT_TRUE(o);
+ EXPECT_EQ((std::vector{'1', '2'}), *o);
+ }
+ {
+ // check std::decay<> in the factory function
+ auto o = makeOptional("String");
+ static_assert(std::is_same>::value,
+ "Bad type deduction in makeOptional()");
+ EXPECT_TRUE(o);
+ EXPECT_STREQ("String", *o);
+ }
+ {
+ auto o = makeOptional("String");
+ static_assert(std::is_same>::value,
+ "Bad type deduction in makeOptional()");
+ EXPECT_TRUE(o);
+ EXPECT_STREQ("String", o->c_str());
+ }
+ {
+ auto o = makeOptional(5, 'b');
+ static_assert(std::is_same>::value,
+ "Bad type deduction in makeOptional()");
+ EXPECT_TRUE(o);
+ EXPECT_STREQ("bbbbb", o->c_str());
+ }
+ {
+ auto o = makeOptional();
+ static_assert(std::is_same>::value,
+ "Bad type deduction in makeOptional()");
+ EXPECT_TRUE(o);
+ EXPECT_STREQ("", o->c_str());
+ }
+}
+
+TEST(Optional, Move) {
+ auto o = makeOptional(std::unique_ptr(new int(10)));
+ {
+ decltype(o) o2 = std::move(o);
+ EXPECT_TRUE(o);
+ EXPECT_TRUE(o2);
+ EXPECT_FALSE(bool(*o));
+ EXPECT_TRUE(bool(*o2));
+ EXPECT_EQ(10, **o2);
+
+ decltype(o) o3;
+ o3 = std::move(o2);
+ EXPECT_TRUE(o2);
+ EXPECT_TRUE(o3);
+ EXPECT_FALSE(bool(*o2));
+ EXPECT_TRUE(bool(*o3));
+ EXPECT_EQ(10, **o3);
+
+ o3 = std::move(o2);
+ EXPECT_TRUE(o2);
+ EXPECT_TRUE(o3);
+ EXPECT_FALSE(bool(*o2));
+ EXPECT_FALSE(bool(*o3));
+ }
+
+ {
+ decltype(o) o1;
+ decltype(o) o2 = std::move(o1);
+ EXPECT_FALSE(o1);
+ EXPECT_FALSE(o2);
+
+ o2 = std::move(o1);
+ EXPECT_FALSE(o1);
+ EXPECT_FALSE(o2);
+
+ decltype(o) o3{kInplace, new int(20)};
+ o3 = std::move(o1);
+ EXPECT_FALSE(o1);
+ EXPECT_FALSE(o3);
+ }
+}
+
+TEST(Optional, Value) {
+ auto o = makeOptional(1);
+ EXPECT_EQ(1, o.value());
+ EXPECT_EQ(1, o.valueOr(2));
+
+ o = kNullopt;
+ EXPECT_EQ(2, o.valueOr(2));
+}
+
+TEST(Optional, Clear) {
+ auto o = makeOptional(1);
+ o.clear();
+ EXPECT_FALSE(o);
+
+ o.clear();
+ EXPECT_FALSE(o);
+}
+
+TEST(Optional, Emplace) {
+ auto o = makeOptional(std::vector{1, 2, 3, 4});
+ o.emplace(3, 1);
+ EXPECT_TRUE(o);
+ EXPECT_EQ((std::vector{1, 1, 1}), *o);
+ EXPECT_EQ(3U, o->capacity());
+
+ o.clear();
+ o.emplace({1, 2});
+ EXPECT_TRUE(o);
+ EXPECT_EQ((std::vector{1, 2}), *o);
+ EXPECT_EQ(2U, o->capacity());
+}
+
+TEST(Optional, Reset) {
+ auto o = makeOptional(std::vector{1, 2, 3, 4});
+ o.reset(std::vector{4, 3});
+ EXPECT_TRUE(o);
+ EXPECT_EQ((std::vector{4, 3}), *o);
+ EXPECT_EQ(2U, o->capacity());
+
+ o.clear();
+ o.reset(std::vector{1});
+ EXPECT_EQ((std::vector{1}), *o);
+ EXPECT_EQ(1U, o->capacity());
+}
+
+TEST(Optional, CompareEqual) {
+ EXPECT_TRUE(makeOptional(1) == makeOptional(1));
+ EXPECT_TRUE(makeOptional(1) == 1);
+ EXPECT_TRUE(1 == makeOptional(1));
+ EXPECT_FALSE(makeOptional(1) == makeOptional(2));
+ EXPECT_FALSE(makeOptional(2) == 1);
+ EXPECT_FALSE(2 == makeOptional(1));
+ EXPECT_TRUE(makeOptional(1) != makeOptional(2));
+ EXPECT_TRUE(makeOptional(1) != 2);
+ EXPECT_TRUE(1 != makeOptional(2));
+
+ EXPECT_FALSE(makeOptional(1) == kNullopt);
+ EXPECT_FALSE(makeOptional(1) == Optional