diff --git a/src/ifcparse/file_reader.cpp b/src/ifcparse/file_reader.cpp index 75d5b92213..549b7de335 100644 --- a/src/ifcparse/file_reader.cpp +++ b/src/ifcparse/file_reader.cpp @@ -75,33 +75,6 @@ full_buffer_impl::full_buffer_impl(const std::string& content, const caller_fed_ , size_(content.size()) { } -size_t full_buffer_impl::size() const { return size_; } - -char full_buffer_impl::get(size_t pos) const { - if (pos >= buf_.size()) { - throw std::out_of_range("get out of range"); - } - return buf_[pos]; -} - -uint64_t full_buffer_impl::get_u64(size_t pos) const { - if (pos + sizeof(uint64_t) > buf_.size()) { - throw std::out_of_range("get_u64 out of range"); - } - uint64_t value; - std::memcpy(&value, buf_.data() + pos, sizeof(value)); - return value; -} - -uint32_t full_buffer_impl::get_u32(size_t pos) const { - if (pos + sizeof(uint32_t) > buf_.size()) { - throw std::out_of_range("get_u32 out of range"); - } - uint32_t value; - std::memcpy(&value, buf_.data() + pos, sizeof(value)); - return value; -} - void full_buffer_impl::push_next_page(const std::string& data) { buf_.insert(buf_.end(), data.begin(), data.end()); size_ = buf_.size(); @@ -247,33 +220,6 @@ mmap_impl::mmap_impl(const std::string& fn) { size_ = static_cast(map_.size()); } -size_t mmap_impl::size() const { return size_; } - -char mmap_impl::get(size_t pos) const { - if (pos >= size_) { - throw std::out_of_range("get out of range"); - } - return map_.data()[pos]; -} - -uint64_t mmap_impl::get_u64(size_t pos) const { - if (pos + sizeof(uint64_t) > size_) { - throw std::out_of_range("get_u64 out of range"); - } - uint64_t value; - std::memcpy(&value, map_.data() + pos, sizeof(value)); - return value; -} - -uint32_t mmap_impl::get_u32(size_t pos) const { - if (pos + sizeof(uint32_t) > size_) { - throw std::out_of_range("get_u32 out of range"); - } - uint32_t value; - std::memcpy(&value, map_.data() + pos, sizeof(value)); - return value; -} - void mmap_impl::push_next_page(const std::string&) { throw std::logic_error("push_next_page: backend does not support pushed mode"); } diff --git a/src/ifcparse/file_reader.h b/src/ifcparse/file_reader.h index a8f924782a..66748b91f3 100644 --- a/src/ifcparse/file_reader.h +++ b/src/ifcparse/file_reader.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -201,10 +202,29 @@ public: explicit full_buffer_impl(const caller_fed_tag& tag); full_buffer_impl(const std::string& content, const caller_fed_tag& tag); - size_t size() const; - char get(size_t position) const; - uint32_t get_u32(size_t position) const; - uint64_t get_u64(size_t position) const; + size_t size() const { return size_; } + char get(size_t position) const { + if (position >= size_) { + throw std::out_of_range("get out of range"); + } + return buf_.data()[position]; + } + uint32_t get_u32(size_t position) const { + if (position + sizeof(uint32_t) > size_) { + throw std::out_of_range("get_u32 out of range"); + } + uint32_t value; + std::memcpy(&value, buf_.data() + position, sizeof(value)); + return value; + } + uint64_t get_u64(size_t position) const { + if (position + sizeof(uint64_t) > size_) { + throw std::out_of_range("get_u64 out of range"); + } + uint64_t value; + std::memcpy(&value, buf_.data() + position, sizeof(value)); + return value; + } void push_next_page(const std::string& page_data); void drop_pages(size_t up_to_position); @@ -249,10 +269,29 @@ class IFC_PARSE_API mmap_impl { public: explicit mmap_impl(const std::string& path); - size_t size() const; - char get(size_t position) const; - uint32_t get_u32(size_t position) const; - uint64_t get_u64(size_t position) const; + size_t size() const { return size_; } + char get(size_t position) const { + if (position >= size_) { + throw std::out_of_range("get out of range"); + } + return map_.data()[position]; + } + uint32_t get_u32(size_t position) const { + if (position + sizeof(uint32_t) > size_) { + throw std::out_of_range("get_u32 out of range"); + } + uint32_t value; + std::memcpy(&value, map_.data() + position, sizeof(value)); + return value; + } + uint64_t get_u64(size_t position) const { + if (position + sizeof(uint64_t) > size_) { + throw std::out_of_range("get_u64 out of range"); + } + uint64_t value; + std::memcpy(&value, map_.data() + position, sizeof(value)); + return value; + } void push_next_page(const std::string& page_data); void drop_pages(size_t up_to_position); diff --git a/src/ifcparse/parse.cpp b/src/ifcparse/parse.cpp index 8ab7fe12e5..7d25a0c3da 100644 --- a/src/ifcparse/parse.cpp +++ b/src/ifcparse/parse.cpp @@ -2412,6 +2412,9 @@ void ifcopenshell::impl::in_memory_file_storage::read_from_stream(Reader* s, con std::vector schemas; instance_streamer streamer(s, file, logger_.get()); + // One inverse record per ~32 bytes of SPF text is a slight over-estimate on + // real models; reserving avoids the doubling copies and the capacity slack. + streamer.inverses().reserve(s->size() / 32); streamer.yield_header_instances(false); if (const auto* header = streamer.header()) { diff --git a/src/ifcparse/storage.h b/src/ifcparse/storage.h index 2322bb449b..d889ff889d 100644 --- a/src/ifcparse/storage.h +++ b/src/ifcparse/storage.h @@ -448,6 +448,7 @@ namespace ifcopenshell { void sort() const { if (!sorted_) { std::sort(base_.begin(), base_.end(), record_less); + base_.shrink_to_fit(); sorted_ = true; invalidate_materialized(); }