From 86df02efd2e254ac7a4ce0ad15f9c6848668c43e Mon Sep 17 00:00:00 2001 From: Davide Faconti Date: Sun, 19 Jan 2025 13:47:04 +0100 Subject: [PATCH] try again --- 3rdparty/CMakeLists.txt | 18 +- 3rdparty/mcap/LICENSE | 202 - 3rdparty/mcap/crc32.hpp | 108 - 3rdparty/mcap/errors.hpp | 116 - 3rdparty/mcap/internal.hpp | 189 - 3rdparty/mcap/intervaltree.hpp | 303 - 3rdparty/mcap/mcap.hpp | 4 - 3rdparty/mcap/read_job_queue.hpp | 147 - 3rdparty/mcap/reader.hpp | 718 - 3rdparty/mcap/reader.inl | 1949 -- 3rdparty/mcap/types.hpp | 405 - 3rdparty/mcap/types.inl | 86 - 3rdparty/mcap/visibility.hpp | 24 - 3rdparty/mcap/writer.hpp | 473 - 3rdparty/mcap/writer.inl | 1102 - 3rdparty/sol/config.hpp | 55 - 3rdparty/sol/forward.hpp | 1321 - 3rdparty/sol/sol.hpp | 28907 ---------------- .../DataLoadMCAP/CMakeLists.txt | 2 - 19 files changed, 5 insertions(+), 36124 deletions(-) delete mode 100644 3rdparty/mcap/LICENSE delete mode 100644 3rdparty/mcap/crc32.hpp delete mode 100644 3rdparty/mcap/errors.hpp delete mode 100644 3rdparty/mcap/internal.hpp delete mode 100644 3rdparty/mcap/intervaltree.hpp delete mode 100644 3rdparty/mcap/mcap.hpp delete mode 100644 3rdparty/mcap/read_job_queue.hpp delete mode 100644 3rdparty/mcap/reader.hpp delete mode 100644 3rdparty/mcap/reader.inl delete mode 100644 3rdparty/mcap/types.hpp delete mode 100644 3rdparty/mcap/types.inl delete mode 100644 3rdparty/mcap/visibility.hpp delete mode 100644 3rdparty/mcap/writer.hpp delete mode 100644 3rdparty/mcap/writer.inl delete mode 100644 3rdparty/sol/config.hpp delete mode 100644 3rdparty/sol/forward.hpp delete mode 100644 3rdparty/sol/sol.hpp diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index 50faecaff..66e71fd0c 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -18,16 +18,9 @@ CPMAddPackage( NAME zstd GITHUB_REPOSITORY facebook/zstd GIT_TAG v1.5.6 - DOWNLOAD_ONLY YES + OPTIONS "ZSTD_BUILD_STATIC ON" "ZSTD_BUILD_SHARED OFF" + SOURCE_SUBDIR build/cmake ) -file(GLOB ZSTD_SOURCES_COMMON ${zstd_SOURCE_DIR}/lib/common/*.c) -file(GLOB ZSTD_SOURCES_COMPRESS ${zstd_SOURCE_DIR}/lib/compress/*.c) -file(GLOB ZSTD_SOURCES_DECOMPRESS ${zstd_SOURCE_DIR}/lib/decompress/*.c) -file(GLOB ZSTD_SOURCES_DICTBUILDER ${zstd_SOURCE_DIR}/lib/dictBuilder/*.c) -list(APPEND ZSTD_SOURCES ${ZSTD_SOURCES_COMMON} ${ZSTD_SOURCES_COMPRESS} ${ZSTD_SOURCES_DECOMPRESS} ${ZSTD_SOURCES_DICTBUILDER}) -add_library(zstd_static STATIC ${ZSTD_SOURCES}) -target_include_directories(zstd_static PUBLIC ${zstd_SOURCE_DIR}/lib) - CPMAddPackage( NAME lz4 @@ -49,8 +42,8 @@ CPMAddPackage( # mcap has no CMake support, so we create our own target add_library(mcap INTERFACE) target_include_directories(mcap INTERFACE "${mcap_SOURCE_DIR}/cpp/mcap/include") -target_link_libraries(mcap INTERFACE zstd_static lz4_static) - +target_link_libraries(mcap INTERFACE libzstd_static lz4_static) +target_include_directories(mcap INTERFACE ${zstd_SOURCE_DIR}/lib) ##### Lua + Sol2 ###### @@ -89,8 +82,7 @@ if (data_tamer_ADDED) add_library(data_tamer_parser INTERFACE) target_include_directories(data_tamer_parser INTERFACE "${data_tamer_SOURCE_DIR}/data_tamer_cpp/include") endif() - - + add_subdirectory( qwt/src ) add_subdirectory( QCodeEditor ) add_subdirectory( color_widgets ) diff --git a/3rdparty/mcap/LICENSE b/3rdparty/mcap/LICENSE deleted file mode 100644 index d64569567..000000000 --- a/3rdparty/mcap/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - 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/mcap/crc32.hpp b/3rdparty/mcap/crc32.hpp deleted file mode 100644 index 7eff3f7cb..000000000 --- a/3rdparty/mcap/crc32.hpp +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include -#include - -namespace mcap::internal { - -/** - * Compute CRC32 lookup tables as described at: - * https://github.com/komrad36/CRC#option-6-1-byte-tabular - * - * An iteration of CRC computation can be performed on 8 bits of input at once. By pre-computing a - * table of the values of CRC(?) for all 2^8 = 256 possible byte values, during the final - * computation we can replace a loop over 8 bits with a single lookup in the table. - * - * For further speedup, we can also pre-compute the values of CRC(?0) for all possible bytes when a - * zero byte is appended. Then we can process two bytes of input at once by computing CRC(AB) = - * CRC(A0) ^ CRC(B), using one lookup in the CRC(?0) table and one lookup in the CRC(?) table. - * - * The same technique applies for any number of bytes to be processed at once, although the speed - * improvements diminish. - * - * @param Polynomial The binary representation of the polynomial to use (reversed, i.e. most - * significant bit represents x^0). - * @param NumTables The number of bytes of input that will be processed at once. - */ -template -struct CRC32Table { -private: - std::array table = {}; - -public: - constexpr CRC32Table() { - for (uint32_t i = 0; i < 256; i++) { - uint32_t r = i; - r = ((r & 1) * Polynomial) ^ (r >> 1); - r = ((r & 1) * Polynomial) ^ (r >> 1); - r = ((r & 1) * Polynomial) ^ (r >> 1); - r = ((r & 1) * Polynomial) ^ (r >> 1); - r = ((r & 1) * Polynomial) ^ (r >> 1); - r = ((r & 1) * Polynomial) ^ (r >> 1); - r = ((r & 1) * Polynomial) ^ (r >> 1); - r = ((r & 1) * Polynomial) ^ (r >> 1); - table[i] = r; - } - for (size_t i = 256; i < table.size(); i++) { - uint32_t value = table[i - 256]; - table[i] = table[value & 0xff] ^ (value >> 8); - } - } - - constexpr uint32_t operator[](size_t index) const { - return table[index]; - } -}; - -inline uint32_t getUint32LE(const std::byte* data) { - return (uint32_t(data[0]) << 0) | (uint32_t(data[1]) << 8) | (uint32_t(data[2]) << 16) | - (uint32_t(data[3]) << 24); -} - -static constexpr CRC32Table<0xedb88320, 8> CRC32_TABLE; - -/** - * Initialize a CRC32 to all 1 bits. - */ -static constexpr uint32_t CRC32_INIT = 0xffffffff; - -/** - * Update a streaming CRC32 calculation. - * - * For performance, this implementation processes the data 8 bytes at a time, using the algorithm - * presented at: https://github.com/komrad36/CRC#option-9-8-byte-tabular - */ -inline uint32_t crc32Update(const uint32_t prev, const std::byte* const data, const size_t length) { - // Process bytes one by one until we reach the proper alignment. - uint32_t r = prev; - size_t offset = 0; - for (; (uintptr_t(data + offset) & alignof(uint32_t)) != 0 && offset < length; offset++) { - r = CRC32_TABLE[(r ^ uint8_t(data[offset])) & 0xff] ^ (r >> 8); - } - if (offset == length) { - return r; - } - - // Process 8 bytes (2 uint32s) at a time. - size_t remainingBytes = length - offset; - for (; remainingBytes >= 8; offset += 8, remainingBytes -= 8) { - r ^= getUint32LE(data + offset); - uint32_t r2 = getUint32LE(data + offset + 4); - r = CRC32_TABLE[0 * 256 + ((r2 >> 24) & 0xff)] ^ CRC32_TABLE[1 * 256 + ((r2 >> 16) & 0xff)] ^ - CRC32_TABLE[2 * 256 + ((r2 >> 8) & 0xff)] ^ CRC32_TABLE[3 * 256 + ((r2 >> 0) & 0xff)] ^ - CRC32_TABLE[4 * 256 + ((r >> 24) & 0xff)] ^ CRC32_TABLE[5 * 256 + ((r >> 16) & 0xff)] ^ - CRC32_TABLE[6 * 256 + ((r >> 8) & 0xff)] ^ CRC32_TABLE[7 * 256 + ((r >> 0) & 0xff)]; - } - - // Process any remaining bytes one by one. - for (; offset < length; offset++) { - r = CRC32_TABLE[(r ^ uint8_t(data[offset])) & 0xff] ^ (r >> 8); - } - return r; -} - -/** Finalize a CRC32 by inverting the output value. */ -inline uint32_t crc32Final(uint32_t crc) { - return crc ^ 0xffffffff; -} - -} // namespace mcap::internal diff --git a/3rdparty/mcap/errors.hpp b/3rdparty/mcap/errors.hpp deleted file mode 100644 index 09c039a9e..000000000 --- a/3rdparty/mcap/errors.hpp +++ /dev/null @@ -1,116 +0,0 @@ -#pragma once - -#include - -namespace mcap { - -/** - * @brief Status codes for MCAP readers and writers. - */ -enum class StatusCode { - Success = 0, - NotOpen, - InvalidSchemaId, - InvalidChannelId, - FileTooSmall, - ReadFailed, - MagicMismatch, - InvalidFile, - InvalidRecord, - InvalidOpCode, - InvalidChunkOffset, - InvalidFooter, - DecompressionFailed, - DecompressionSizeMismatch, - UnrecognizedCompression, - OpenFailed, - MissingStatistics, - InvalidMessageReadOptions, - NoMessageIndexesAvailable, -}; - -/** - * @brief Wraps a status code and string message carrying additional context. - */ -struct [[nodiscard]] Status { - StatusCode code; - std::string message; - - Status() - : code(StatusCode::Success) {} - - Status(StatusCode code) - : code(code) { - switch (code) { - case StatusCode::Success: - break; - case StatusCode::NotOpen: - message = "not open"; - break; - case StatusCode::InvalidSchemaId: - message = "invalid schema id"; - break; - case StatusCode::InvalidChannelId: - message = "invalid channel id"; - break; - case StatusCode::FileTooSmall: - message = "file too small"; - break; - case StatusCode::ReadFailed: - message = "read failed"; - break; - case StatusCode::MagicMismatch: - message = "magic mismatch"; - break; - case StatusCode::InvalidFile: - message = "invalid file"; - break; - case StatusCode::InvalidRecord: - message = "invalid record"; - break; - case StatusCode::InvalidOpCode: - message = "invalid opcode"; - break; - case StatusCode::InvalidChunkOffset: - message = "invalid chunk offset"; - break; - case StatusCode::InvalidFooter: - message = "invalid footer"; - break; - case StatusCode::DecompressionFailed: - message = "decompression failed"; - break; - case StatusCode::DecompressionSizeMismatch: - message = "decompression size mismatch"; - break; - case StatusCode::UnrecognizedCompression: - message = "unrecognized compression"; - break; - case StatusCode::OpenFailed: - message = "open failed"; - break; - case StatusCode::MissingStatistics: - message = "missing statistics"; - break; - case StatusCode::InvalidMessageReadOptions: - message = "message read options conflict"; - break; - case StatusCode::NoMessageIndexesAvailable: - message = "file has no message indices"; - break; - default: - message = "unknown"; - break; - } - } - - Status(StatusCode code, const std::string& message) - : code(code) - , message(message) {} - - bool ok() const { - return code == StatusCode::Success; - } -}; - -} // namespace mcap diff --git a/3rdparty/mcap/internal.hpp b/3rdparty/mcap/internal.hpp deleted file mode 100644 index 4faedd0b2..000000000 --- a/3rdparty/mcap/internal.hpp +++ /dev/null @@ -1,189 +0,0 @@ -#pragma once - -#include "types.hpp" -#include - -// Do not compile on systems with non-8-bit bytes -static_assert(std::numeric_limits::digits == 8); - -namespace mcap { - -namespace internal { - -constexpr uint64_t MinHeaderLength = /* magic bytes */ sizeof(Magic) + - /* opcode */ 1 + - /* record length */ 8 + - /* profile length */ 4 + - /* library length */ 4; -constexpr uint64_t FooterLength = /* opcode */ 1 + - /* record length */ 8 + - /* summary start */ 8 + - /* summary offset start */ 8 + - /* summary crc */ 4 + - /* magic bytes */ sizeof(Magic); - -inline std::string ToHex(uint8_t byte) { - std::string result{2, '\0'}; - result[0] = "0123456789ABCDEF"[(uint8_t(byte) >> 4) & 0x0F]; - result[1] = "0123456789ABCDEF"[uint8_t(byte) & 0x0F]; - return result; -} -inline std::string ToHex(std::byte byte) { - return ToHex(uint8_t(byte)); -} - -inline std::string to_string(const std::string& arg) { - return arg; -} -inline std::string to_string(std::string_view arg) { - return std::string(arg); -} -inline std::string to_string(const char* arg) { - return std::string(arg); -} -template -[[nodiscard]] inline std::string StrCat(T&&... args) { - using mcap::internal::to_string; - using std::to_string; - return ("" + ... + to_string(std::forward(args))); -} - -inline uint32_t KeyValueMapSize(const KeyValueMap& map) { - size_t size = 0; - for (const auto& [key, value] : map) { - size += 4 + key.size() + 4 + value.size(); - } - return (uint32_t)(size); -} - -inline const std::string CompressionString(Compression compression) { - switch (compression) { - case Compression::None: - default: - return std::string{}; - case Compression::Lz4: - return "lz4"; - case Compression::Zstd: - return "zstd"; - } -} - -inline uint16_t ParseUint16(const std::byte* data) { - return uint16_t(data[0]) | (uint16_t(data[1]) << 8); -} - -inline uint32_t ParseUint32(const std::byte* data) { - return uint32_t(data[0]) | (uint32_t(data[1]) << 8) | (uint32_t(data[2]) << 16) | - (uint32_t(data[3]) << 24); -} - -inline Status ParseUint32(const std::byte* data, uint64_t maxSize, uint32_t* output) { - if (maxSize < 4) { - const auto msg = StrCat("cannot read uint32 from ", maxSize, " bytes"); - return Status{StatusCode::InvalidRecord, msg}; - } - *output = ParseUint32(data); - return StatusCode::Success; -} - -inline uint64_t ParseUint64(const std::byte* data) { - return uint64_t(data[0]) | (uint64_t(data[1]) << 8) | (uint64_t(data[2]) << 16) | - (uint64_t(data[3]) << 24) | (uint64_t(data[4]) << 32) | (uint64_t(data[5]) << 40) | - (uint64_t(data[6]) << 48) | (uint64_t(data[7]) << 56); -} - -inline Status ParseUint64(const std::byte* data, uint64_t maxSize, uint64_t* output) { - if (maxSize < 8) { - const auto msg = StrCat("cannot read uint64 from ", maxSize, " bytes"); - return Status{StatusCode::InvalidRecord, msg}; - } - *output = ParseUint64(data); - return StatusCode::Success; -} - -inline Status ParseStringView(const std::byte* data, uint64_t maxSize, std::string_view* output) { - uint32_t size = 0; - if (auto status = ParseUint32(data, maxSize, &size); !status.ok()) { - const auto msg = StrCat("cannot read string size: ", status.message); - return Status{StatusCode::InvalidRecord, msg}; - } - if (uint64_t(size) > (maxSize - 4)) { - const auto msg = StrCat("string size ", size, " exceeds remaining bytes ", (maxSize - 4)); - return Status(StatusCode::InvalidRecord, msg); - } - *output = std::string_view(reinterpret_cast(data + 4), size); - return StatusCode::Success; -} - -inline Status ParseString(const std::byte* data, uint64_t maxSize, std::string* output) { - uint32_t size = 0; - if (auto status = ParseUint32(data, maxSize, &size); !status.ok()) { - return status; - } - if (uint64_t(size) > (maxSize - 4)) { - const auto msg = StrCat("string size ", size, " exceeds remaining bytes ", (maxSize - 4)); - return Status(StatusCode::InvalidRecord, msg); - } - *output = std::string(reinterpret_cast(data + 4), size); - return StatusCode::Success; -} - -inline Status ParseByteArray(const std::byte* data, uint64_t maxSize, ByteArray* output) { - uint32_t size = 0; - if (auto status = ParseUint32(data, maxSize, &size); !status.ok()) { - return status; - } - if (uint64_t(size) > (maxSize - 4)) { - const auto msg = StrCat("byte array size ", size, " exceeds remaining bytes ", (maxSize - 4)); - return Status(StatusCode::InvalidRecord, msg); - } - output->resize(size); - std::memcpy(output->data(), data + 4, size); - return StatusCode::Success; -} - -inline Status ParseKeyValueMap(const std::byte* data, uint64_t maxSize, KeyValueMap* output) { - uint32_t sizeInBytes = 0; - if (auto status = ParseUint32(data, maxSize, &sizeInBytes); !status.ok()) { - return status; - } - if (sizeInBytes > (maxSize - 4)) { - const auto msg = - StrCat("key-value map size ", sizeInBytes, " exceeds remaining bytes ", (maxSize - 4)); - return Status(StatusCode::InvalidRecord, msg); - } - - // Account for the byte size prefix in sizeInBytes to make the bounds checking - // below simpler - sizeInBytes += 4; - - output->clear(); - uint64_t pos = 4; - while (pos < sizeInBytes) { - std::string_view key; - if (auto status = ParseStringView(data + pos, sizeInBytes - pos, &key); !status.ok()) { - const auto msg = StrCat("cannot read key-value map key at pos ", pos, ": ", status.message); - return Status{StatusCode::InvalidRecord, msg}; - } - pos += 4 + key.size(); - std::string_view value; - if (auto status = ParseStringView(data + pos, sizeInBytes - pos, &value); !status.ok()) { - const auto msg = StrCat("cannot read key-value map value for key \"", key, "\" at pos ", pos, - ": ", status.message); - return Status{StatusCode::InvalidRecord, msg}; - } - pos += 4 + value.size(); - output->emplace(key, value); - } - return StatusCode::Success; -} - -inline std::string MagicToHex(const std::byte* data) { - return internal::ToHex(data[0]) + internal::ToHex(data[1]) + internal::ToHex(data[2]) + - internal::ToHex(data[3]) + internal::ToHex(data[4]) + internal::ToHex(data[5]) + - internal::ToHex(data[6]) + internal::ToHex(data[7]); -} - -} // namespace internal - -} // namespace mcap diff --git a/3rdparty/mcap/intervaltree.hpp b/3rdparty/mcap/intervaltree.hpp deleted file mode 100644 index b9c2b6ea4..000000000 --- a/3rdparty/mcap/intervaltree.hpp +++ /dev/null @@ -1,303 +0,0 @@ -// Adapted from - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace mcap::internal { - -template -class Interval { -public: - Scalar start; - Scalar stop; - Value value; - Interval(const Scalar& s, const Scalar& e, const Value& v) - : start(std::min(s, e)) - , stop(std::max(s, e)) - , value(v) {} -}; - -template -Value intervalStart(const Interval& i) { - return i.start; -} - -template -Value intervalStop(const Interval& i) { - return i.stop; -} - -template -std::ostream& operator<<(std::ostream& out, const Interval& i) { - out << "Interval(" << i.start << ", " << i.stop << "): " << i.value; - return out; -} - -template -class IntervalTree { -public: - using interval = Interval; - using interval_vector = std::vector; - - struct IntervalStartCmp { - bool operator()(const interval& a, const interval& b) { - return a.start < b.start; - } - }; - - struct IntervalStopCmp { - bool operator()(const interval& a, const interval& b) { - return a.stop < b.stop; - } - }; - - IntervalTree() - : left(nullptr) - , right(nullptr) - , center(Scalar(0)) {} - - ~IntervalTree() = default; - - std::unique_ptr clone() const { - return std::unique_ptr(new IntervalTree(*this)); - } - - IntervalTree(const IntervalTree& other) - : intervals(other.intervals) - , left(other.left ? other.left->clone() : nullptr) - , right(other.right ? other.right->clone() : nullptr) - , center(other.center) {} - - IntervalTree& operator=(IntervalTree&&) = default; - IntervalTree(IntervalTree&&) = default; - - IntervalTree& operator=(const IntervalTree& other) { - center = other.center; - intervals = other.intervals; - left = other.left ? other.left->clone() : nullptr; - right = other.right ? other.right->clone() : nullptr; - return *this; - } - - IntervalTree(interval_vector&& ivals, std::size_t depth = 16, std::size_t minbucket = 64, - std::size_t maxbucket = 512, Scalar leftextent = 0, Scalar rightextent = 0) - : left(nullptr) - , right(nullptr) { - --depth; - const auto minmaxStop = std::minmax_element(ivals.begin(), ivals.end(), IntervalStopCmp()); - const auto minmaxStart = std::minmax_element(ivals.begin(), ivals.end(), IntervalStartCmp()); - if (!ivals.empty()) { - center = (minmaxStart.first->start + minmaxStop.second->stop) / 2; - } - if (leftextent == 0 && rightextent == 0) { - // sort intervals by start - std::sort(ivals.begin(), ivals.end(), IntervalStartCmp()); - } else { - assert(std::is_sorted(ivals.begin(), ivals.end(), IntervalStartCmp())); - } - if (depth == 0 || (ivals.size() < minbucket && ivals.size() < maxbucket)) { - std::sort(ivals.begin(), ivals.end(), IntervalStartCmp()); - intervals = std::move(ivals); - assert(is_valid().first); - return; - } else { - Scalar leftp = 0; - Scalar rightp = 0; - - if (leftextent || rightextent) { - leftp = leftextent; - rightp = rightextent; - } else { - leftp = ivals.front().start; - rightp = std::max_element(ivals.begin(), ivals.end(), IntervalStopCmp())->stop; - } - - interval_vector lefts; - interval_vector rights; - - for (typename interval_vector::const_iterator i = ivals.begin(); i != ivals.end(); ++i) { - const interval& interval = *i; - if (interval.stop < center) { - lefts.push_back(interval); - } else if (interval.start > center) { - rights.push_back(interval); - } else { - assert(interval.start <= center); - assert(center <= interval.stop); - intervals.push_back(interval); - } - } - - if (!lefts.empty()) { - left.reset(new IntervalTree(std::move(lefts), depth, minbucket, maxbucket, leftp, center)); - } - if (!rights.empty()) { - right.reset( - new IntervalTree(std::move(rights), depth, minbucket, maxbucket, center, rightp)); - } - } - assert(is_valid().first); - } - - // Call f on all intervals near the range [start, stop]: - template - void visit_near(const Scalar& start, const Scalar& stop, UnaryFunction f) const { - if (!intervals.empty() && !(stop < intervals.front().start)) { - for (auto& i : intervals) { - f(i); - } - } - if (left && start <= center) { - left->visit_near(start, stop, f); - } - if (right && stop >= center) { - right->visit_near(start, stop, f); - } - } - - // Call f on all intervals crossing pos - template - void visit_overlapping(const Scalar& pos, UnaryFunction f) const { - visit_overlapping(pos, pos, f); - } - - // Call f on all intervals overlapping [start, stop] - template - void visit_overlapping(const Scalar& start, const Scalar& stop, UnaryFunction f) const { - auto filterF = [&](const interval& interval) { - if (interval.stop >= start && interval.start <= stop) { - // Only apply f if overlapping - f(interval); - } - }; - visit_near(start, stop, filterF); - } - - // Call f on all intervals contained within [start, stop] - template - void visit_contained(const Scalar& start, const Scalar& stop, UnaryFunction f) const { - auto filterF = [&](const interval& interval) { - if (start <= interval.start && interval.stop <= stop) { - f(interval); - } - }; - visit_near(start, stop, filterF); - } - - interval_vector find_overlapping(const Scalar& start, const Scalar& stop) const { - interval_vector result; - visit_overlapping(start, stop, [&](const interval& interval) { - result.emplace_back(interval); - }); - return result; - } - - interval_vector find_contained(const Scalar& start, const Scalar& stop) const { - interval_vector result; - visit_contained(start, stop, [&](const interval& interval) { - result.push_back(interval); - }); - return result; - } - - bool empty() const { - if (left && !left->empty()) { - return false; - } - if (!intervals.empty()) { - return false; - } - if (right && !right->empty()) { - return false; - } - return true; - } - - template - void visit_all(UnaryFunction f) const { - if (left) { - left->visit_all(f); - } - std::for_each(intervals.begin(), intervals.end(), f); - if (right) { - right->visit_all(f); - } - } - - std::pair extent() const { - struct Extent { - std::pair x{std::numeric_limits::max(), - std::numeric_limits::min()}; - void operator()(const interval& interval) { - x.first = std::min(x.first, interval.start); - x.second = std::max(x.second, interval.stop); - } - }; - Extent extent; - - visit_all([&](const interval& interval) { - extent(interval); - }); - return extent.x; - } - - // Check all constraints. - // If first is false, second is invalid. - std::pair> is_valid() const { - const auto minmaxStop = - std::minmax_element(intervals.begin(), intervals.end(), IntervalStopCmp()); - const auto minmaxStart = - std::minmax_element(intervals.begin(), intervals.end(), IntervalStartCmp()); - - std::pair> result = { - true, {std::numeric_limits::max(), std::numeric_limits::min()}}; - if (!intervals.empty()) { - result.second.first = std::min(result.second.first, minmaxStart.first->start); - result.second.second = std::min(result.second.second, minmaxStop.second->stop); - } - if (left) { - auto valid = left->is_valid(); - result.first &= valid.first; - result.second.first = std::min(result.second.first, valid.second.first); - result.second.second = std::min(result.second.second, valid.second.second); - if (!result.first) { - return result; - } - if (valid.second.second >= center) { - result.first = false; - return result; - } - } - if (right) { - auto valid = right->is_valid(); - result.first &= valid.first; - result.second.first = std::min(result.second.first, valid.second.first); - result.second.second = std::min(result.second.second, valid.second.second); - if (!result.first) { - return result; - } - if (valid.second.first <= center) { - result.first = false; - return result; - } - } - if (!std::is_sorted(intervals.begin(), intervals.end(), IntervalStartCmp())) { - result.first = false; - } - return result; - } - -private: - interval_vector intervals; - std::unique_ptr left; - std::unique_ptr right; - Scalar center; -}; - -} // namespace mcap::internal diff --git a/3rdparty/mcap/mcap.hpp b/3rdparty/mcap/mcap.hpp deleted file mode 100644 index 71f479cd8..000000000 --- a/3rdparty/mcap/mcap.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#include "reader.hpp" -#include "writer.hpp" diff --git a/3rdparty/mcap/read_job_queue.hpp b/3rdparty/mcap/read_job_queue.hpp deleted file mode 100644 index 7faf4468a..000000000 --- a/3rdparty/mcap/read_job_queue.hpp +++ /dev/null @@ -1,147 +0,0 @@ -#pragma once - -#include "types.hpp" -#include -#include - -namespace mcap::internal { - -// Helper for writing compile-time exhaustive variant visitors. -template -inline constexpr bool always_false_v = false; - -/** - * @brief A job to read a specific message at offset `offset` from the decompressed chunk - * stored in `chunkReaderIndex`. A timestamp is provided to order this job relative to other jobs. - */ -struct ReadMessageJob { - Timestamp timestamp; - RecordOffset offset; - size_t chunkReaderIndex; -}; - -/** - * @brief A job to decompress the chunk starting at `chunkStartOffset`. The message indices - * starting directly after the chunk record and ending at `messageIndexEndOffset` will be used to - * find specific messages within the chunk. - */ -struct DecompressChunkJob { - Timestamp messageStartTime; - Timestamp messageEndTime; - ByteOffset chunkStartOffset; - ByteOffset messageIndexEndOffset; -}; - -/** - * @brief A union of jobs that an indexed MCAP reader executes. - */ -using ReadJob = std::variant; - -/** - * @brief A priority queue of jobs for an indexed MCAP reader to execute. - */ -struct ReadJobQueue { -private: - bool reverse_ = false; - std::vector heap_; - - /** - * @brief return the timestamp key that should be used to compare jobs. - */ - static Timestamp TimeComparisonKey(const ReadJob& job, bool reverse) { - Timestamp result = 0; - std::visit( - [&](auto&& arg) { - using T = std::decay_t; - if constexpr (std::is_same_v) { - result = arg.timestamp; - } else if constexpr (std::is_same_v) { - if (reverse) { - result = arg.messageEndTime; - } else { - result = arg.messageStartTime; - } - } else { - static_assert(always_false_v, "non-exhaustive visitor!"); - } - }, - job); - return result; - } - static RecordOffset PositionComparisonKey(const ReadJob& job, bool reverse) { - RecordOffset result; - std::visit( - [&](auto&& arg) { - using T = std::decay_t; - if constexpr (std::is_same_v) { - result = arg.offset; - } else if constexpr (std::is_same_v) { - if (reverse) { - result.offset = arg.messageIndexEndOffset; - } else { - result.offset = arg.chunkStartOffset; - } - } else { - static_assert(always_false_v, "non-exhaustive visitor!"); - } - }, - job); - return result; - } - - static bool CompareForward(const ReadJob& a, const ReadJob& b) { - auto aTimestamp = TimeComparisonKey(a, false); - auto bTimestamp = TimeComparisonKey(b, false); - if (aTimestamp == bTimestamp) { - return PositionComparisonKey(a, false) > PositionComparisonKey(b, false); - } - return aTimestamp > bTimestamp; - } - - static bool CompareReverse(const ReadJob& a, const ReadJob& b) { - auto aTimestamp = TimeComparisonKey(a, true); - auto bTimestamp = TimeComparisonKey(b, true); - if (aTimestamp == bTimestamp) { - return PositionComparisonKey(a, true) < PositionComparisonKey(b, true); - } - return aTimestamp < bTimestamp; - } - -public: - explicit ReadJobQueue(bool reverse) - : reverse_(reverse) {} - void push(DecompressChunkJob&& decompressChunkJob) { - heap_.emplace_back(std::move(decompressChunkJob)); - if (!reverse_) { - std::push_heap(heap_.begin(), heap_.end(), CompareForward); - } else { - std::push_heap(heap_.begin(), heap_.end(), CompareReverse); - } - } - - void push(ReadMessageJob&& readMessageJob) { - heap_.emplace_back(std::move(readMessageJob)); - if (!reverse_) { - std::push_heap(heap_.begin(), heap_.end(), CompareForward); - } else { - std::push_heap(heap_.begin(), heap_.end(), CompareReverse); - } - } - - ReadJob pop() { - if (!reverse_) { - std::pop_heap(heap_.begin(), heap_.end(), CompareForward); - } else { - std::pop_heap(heap_.begin(), heap_.end(), CompareReverse); - } - auto popped = heap_.back(); - heap_.pop_back(); - return popped; - } - - size_t len() const { - return heap_.size(); - } -}; - -} // namespace mcap::internal diff --git a/3rdparty/mcap/reader.hpp b/3rdparty/mcap/reader.hpp deleted file mode 100644 index 43ccbaf58..000000000 --- a/3rdparty/mcap/reader.hpp +++ /dev/null @@ -1,718 +0,0 @@ -#pragma once - -#include "intervaltree.hpp" -#include "read_job_queue.hpp" -#include "types.hpp" -#include "visibility.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mcap { - -enum struct ReadSummaryMethod { - /** - * @brief Parse the Summary section to produce seeking indexes and summary - * statistics. If the Summary section is not present or corrupt, a failure - * Status is returned and the seeking indexes and summary statistics are not - * populated. - */ - NoFallbackScan, - /** - * @brief If the Summary section is missing or incomplete, allow falling back - * to reading the file sequentially to produce seeking indexes and summary - * statistics. - */ - AllowFallbackScan, - /** - * @brief Read the file sequentially from Header to DataEnd to produce seeking - * indexes and summary statistics. - */ - ForceScan, -}; - -/** - * @brief An abstract interface for reading MCAP data. - */ -struct MCAP_PUBLIC IReadable { - virtual ~IReadable() = default; - - /** - * @brief Returns the size of the file in bytes. - * - * @return uint64_t The total number of bytes in the MCAP file. - */ - virtual uint64_t size() const = 0; - /** - * @brief This method is called by MCAP reader classes when they need to read - * a portion of the file. - * - * @param output A pointer to a pointer to the buffer to write to. This method - * is expected to either maintain an internal buffer, read data into it, and - * update this pointer to point at the internal buffer, or update this - * pointer to point directly at the source data if possible. The pointer and - * data must remain valid and unmodified until the next call to read(). - * @param offset The offset in bytes from the beginning of the file to read. - * @param size The number of bytes to read. - * @return uint64_t Number of bytes actually read. This may be less than the - * requested size if the end of the file is reached. The output pointer must - * be readable from `output` to `output + size`. If the read fails, this - * method should return 0. - */ - virtual uint64_t read(std::byte** output, uint64_t offset, uint64_t size) = 0; -}; - -/** - * @brief IReadable implementation wrapping a FILE* pointer created by fopen() - * and a read buffer. - */ -class MCAP_PUBLIC FileReader final : public IReadable { -public: - FileReader(std::FILE* file); - - uint64_t size() const override; - uint64_t read(std::byte** output, uint64_t offset, uint64_t size) override; - -private: - std::FILE* file_; - std::vector buffer_; - uint64_t size_; - uint64_t position_; -}; - -/** - * @brief IReadable implementation wrapping a std::ifstream input file stream. - */ -class MCAP_PUBLIC FileStreamReader final : public IReadable { -public: - FileStreamReader(std::ifstream& stream); - - uint64_t size() const override; - uint64_t read(std::byte** output, uint64_t offset, uint64_t size) override; - -private: - std::ifstream& stream_; - std::vector buffer_; - uint64_t size_; - uint64_t position_; -}; - -/** - * @brief An abstract interface for compressed readers. - */ -class MCAP_PUBLIC ICompressedReader : public IReadable { -public: - virtual ~ICompressedReader() override = default; - - /** - * @brief Reset the reader state, clearing any internal buffers and state, and - * initialize with new compressed data. - * - * @param data Compressed data to read from. - * @param size Size of the compressed data in bytes. - * @param uncompressedSize Size of the data in bytes after decompression. A - * buffer of this size will be allocated for the uncompressed data. - */ - virtual void reset(const std::byte* data, uint64_t size, uint64_t uncompressedSize) = 0; - /** - * @brief Report the current status of decompression. A StatusCode other than - * `StatusCode::Success` after `reset()` is called indicates the decompression - * was not successful and the reader is in an invalid state. - */ - virtual Status status() const = 0; -}; - -/** - * @brief A "null" compressed reader that directly passes through uncompressed - * data. No internal buffers are allocated. - */ -class MCAP_PUBLIC BufferReader final : public ICompressedReader { -public: - void reset(const std::byte* data, uint64_t size, uint64_t uncompressedSize) override; - uint64_t read(std::byte** output, uint64_t offset, uint64_t size) override; - uint64_t size() const override; - Status status() const override; - - BufferReader() = default; - BufferReader(const BufferReader&) = delete; - BufferReader& operator=(const BufferReader&) = delete; - BufferReader(BufferReader&&) = delete; - BufferReader& operator=(BufferReader&&) = delete; - -private: - const std::byte* data_; - uint64_t size_; -}; - -/** - * @brief ICompressedReader implementation that decompresses Zstandard - * (https://facebook.github.io/zstd/) data. - */ -class MCAP_PUBLIC ZStdReader final : public ICompressedReader { -public: - void reset(const std::byte* data, uint64_t size, uint64_t uncompressedSize) override; - uint64_t read(std::byte** output, uint64_t offset, uint64_t size) override; - uint64_t size() const override; - Status status() const override; - - /** - * @brief Decompresses an entire Zstd-compressed chunk into `output`. - * - * @param data The Zstd-compressed input chunk. - * @param compressedSize The size of the Zstd-compressed input. - * @param uncompressedSize The size of the data once uncompressed. - * @param output The output vector. This will be resized to `uncompressedSize` to fit the data, - * or 0 if the decompression encountered an error. - * @return Status - */ - static Status DecompressAll(const std::byte* data, uint64_t compressedSize, - uint64_t uncompressedSize, ByteArray* output); - ZStdReader() = default; - ZStdReader(const ZStdReader&) = delete; - ZStdReader& operator=(const ZStdReader&) = delete; - ZStdReader(ZStdReader&&) = delete; - ZStdReader& operator=(ZStdReader&&) = delete; - -private: - Status status_; - ByteArray uncompressedData_; -}; - -/** - * @brief ICompressedReader implementation that decompresses LZ4 - * (https://lz4.github.io/lz4/) data. - */ -class MCAP_PUBLIC LZ4Reader final : public ICompressedReader { -public: - void reset(const std::byte* data, uint64_t size, uint64_t uncompressedSize) override; - uint64_t read(std::byte** output, uint64_t offset, uint64_t size) override; - uint64_t size() const override; - Status status() const override; - - /** - * @brief Decompresses an entire LZ4-encoded chunk into `output`. - * - * @param data The LZ4-compressed input chunk. - * @param size The size of the LZ4-compressed input. - * @param uncompressedSize The size of the data once uncompressed. - * @param output The output vector. This will be resized to `uncompressedSize` to fit the data, - * or 0 if the decompression encountered an error. - * @return Status - */ - Status decompressAll(const std::byte* data, uint64_t size, uint64_t uncompressedSize, - ByteArray* output); - LZ4Reader(); - LZ4Reader(const LZ4Reader&) = delete; - LZ4Reader& operator=(const LZ4Reader&) = delete; - LZ4Reader(LZ4Reader&&) = delete; - LZ4Reader& operator=(LZ4Reader&&) = delete; - ~LZ4Reader() override; - -private: - void* decompressionContext_ = nullptr; // LZ4F_dctx* - Status status_; - const std::byte* compressedData_; - ByteArray uncompressedData_; - uint64_t compressedSize_; - uint64_t uncompressedSize_; -}; - -struct LinearMessageView; - -/** - * @brief Options for reading messages out of an MCAP file. - */ -struct MCAP_PUBLIC ReadMessageOptions { -public: - /** - * @brief Only messages with log timestamps greater or equal to startTime will be included. - */ - Timestamp startTime = 0; - /** - * @brief Only messages with log timestamps less than endTime will be included. - */ - Timestamp endTime = MaxTime; - /** - * @brief If provided, `topicFilter` is called on all topics found in the MCAP file. If - * `topicFilter` returns true for a given channel, messages from that channel will be included. - * if not provided, messages from all channels are provided. - */ - std::function topicFilter; - enum struct ReadOrder { FileOrder, LogTimeOrder, ReverseLogTimeOrder }; - /** - * @brief Set the expected order that messages should be returned in. - * if readOrder == FileOrder, messages will be returned in the order they appear in the MCAP file. - * if readOrder == LogTimeOrder, messages will be returned in ascending log time order. - * if readOrder == ReverseLogTimeOrder, messages will be returned in descending log time order. - */ - ReadOrder readOrder = ReadOrder::FileOrder; - - ReadMessageOptions(Timestamp start, Timestamp end) - : startTime(start) - , endTime(end) {} - - ReadMessageOptions() = default; - - /** - * @brief validate the configuration. - */ - Status validate() const; -}; - -/** - * @brief Provides a read interface to an MCAP file. - */ -class MCAP_PUBLIC McapReader final { -public: - ~McapReader(); - - /** - * @brief Opens an MCAP file for reading from an already constructed IReadable - * implementation. - * - * @param reader An implementation of the IReader interface that provides raw - * MCAP data. - * @return Status StatusCode::Success on success. If a non-success Status is - * returned, the data source is not considered open and McapReader is not - * usable until `open()` is called and a success response is returned. - */ - Status open(IReadable& reader); - /** - * @brief Opens an MCAP file for reading from a given filename. - * - * @param filename Filename to open. - * @return Status StatusCode::Success on success. If a non-success Status is - * returned, the data source is not considered open and McapReader is not - * usable until `open()` is called and a success response is returned. - */ - Status open(std::string_view filename); - /** - * @brief Opens an MCAP file for reading from a std::ifstream input file - * stream. - * - * @param stream Input file stream to read MCAP data from. - * @return Status StatusCode::Success on success. If a non-success Status is - * returned, the file is not considered open and McapReader is not usable - * until `open()` is called and a success response is returned. - */ - Status open(std::ifstream& stream); - - /** - * @brief Closes the MCAP file, clearing any internal data structures and - * state and dropping the data source reference. - * - */ - void close(); - - /** - * @brief Read and parse the Summary section at the end of the MCAP file, if - * available. This will populate internal indexes to allow for efficient - * summarization and random access. This method will automatically be called - * upon requesting summary data or first seek if Summary section parsing is - * allowed by the configuration options. - */ - Status readSummary( - ReadSummaryMethod method, const ProblemCallback& onProblem = [](const Status&) {}); - - /** - * @brief Returns an iterable view with `begin()` and `end()` methods for - * iterating Messages in the MCAP file. If a non-zero `startTime` is provided, - * this will first parse the Summary section (by calling `readSummary()`) if - * allowed by the configuration options and it has not been parsed yet. - * - * @param startTime Optional start time in nanoseconds. Messages before this - * time will not be returned. - * @param endTime Optional end time in nanoseconds. Messages equal to or after - * this time will not be returned. - */ - LinearMessageView readMessages(Timestamp startTime = 0, Timestamp endTime = MaxTime); - /** - * @brief Returns an iterable view with `begin()` and `end()` methods for - * iterating Messages in the MCAP file. If a non-zero `startTime` is provided, - * this will first parse the Summary section (by calling `readSummary()`) if - * allowed by the configuration options and it has not been parsed yet. - * - * @param onProblem A callback that will be called when a parsing error - * occurs. Problems can either be recoverable, indicating some data could - * not be read, or non-recoverable, stopping the iteration. - * @param startTime Optional start time in nanoseconds. Messages before this - * time will not be returned. - * @param endTime Optional end time in nanoseconds. Messages equal to or after - * this time will not be returned. - */ - LinearMessageView readMessages(const ProblemCallback& onProblem, Timestamp startTime = 0, - Timestamp endTime = MaxTime); - - /** - * @brief Returns an iterable view with `begin()` and `end()` methods for - * iterating Messages in the MCAP file. - * Uses the options from `options` to select the messages that are yielded. - */ - LinearMessageView readMessages(const ProblemCallback& onProblem, - const ReadMessageOptions& options); - - /** - * @brief Returns starting and ending byte offsets that must be read to - * iterate all messages in the given time range. If `readSummary()` has been - * successfully called and the recording contains Chunk records, this range - * will be narrowed to Chunk records that contain messages in the given time - * range. Otherwise, this range will be the entire Data section if the Data - * End record has been found or the entire file otherwise. - * - * This method is automatically used by `readMessages()`, and only needs to be - * called directly if the caller is manually constructing an iterator. - * - * @param startTime Start time in nanoseconds. - * @param endTime Optional end time in nanoseconds. - * @return Start and end byte offsets. - */ - std::pair byteRange(Timestamp startTime, - Timestamp endTime = MaxTime) const; - - /** - * @brief Returns a pointer to the IReadable data source backing this reader. - * Will return nullptr if the reader is not open. - */ - IReadable* dataSource(); - - /** - * @brief Returns the parsed Header record, if it has been encountered. - */ - const std::optional
& header() const; - /** - * @brief Returns the parsed Footer record, if it has been encountered. - */ - const std::optional