/src/assimp/code/AssetLib/MDL/HalfLife/HL1DataBuffer.h
Line | Count | Source |
1 | | /* |
2 | | --------------------------------------------------------------------------- |
3 | | Open Asset Import Library (assimp) |
4 | | --------------------------------------------------------------------------- |
5 | | |
6 | | Copyright (c) 2006-2026, assimp team |
7 | | |
8 | | All rights reserved. |
9 | | |
10 | | Redistribution and use of this software in source and binary forms, |
11 | | with or without modification, are permitted provided that the following |
12 | | conditions are met: |
13 | | |
14 | | * Redistributions of source code must retain the above |
15 | | copyright notice, this list of conditions and the |
16 | | following disclaimer. |
17 | | |
18 | | * Redistributions in binary form must reproduce the above |
19 | | copyright notice, this list of conditions and the |
20 | | following disclaimer in the documentation and/or other |
21 | | materials provided with the distribution. |
22 | | |
23 | | * Neither the name of the assimp team, nor the names of its |
24 | | contributors may be used to endorse or promote products |
25 | | derived from this software without specific prior |
26 | | written permission of the assimp team. |
27 | | |
28 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
29 | | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
30 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
31 | | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
32 | | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
33 | | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
34 | | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
35 | | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
36 | | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
37 | | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
38 | | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
39 | | --------------------------------------------------------------------------- |
40 | | */ |
41 | | |
42 | | /** @file HL1DataBuffer.h |
43 | | * @brief Declaration of the Half-Life 1 data buffer. |
44 | | */ |
45 | | |
46 | | #ifndef AI_HL1DATABUFFER_INCLUDED |
47 | | #define AI_HL1DATABUFFER_INCLUDED |
48 | | |
49 | | #include <assimp/Exceptional.h> |
50 | | #include <assimp/defs.h> |
51 | | #include <cstddef> |
52 | | #include <memory> |
53 | | |
54 | | namespace Assimp { |
55 | | namespace MDL { |
56 | | namespace HalfLife { |
57 | | |
58 | | /** |
59 | | * \brief Lightweight byte buffer wrapper for HL1 binary parsing. |
60 | | * |
61 | | * Acts as either: |
62 | | * - a non-owning view into external memory, or |
63 | | * - an owning buffer backed by a unique_ptr. |
64 | | * |
65 | | * Copy is disabled to avoid accidental double-ownership; move is supported. |
66 | | */ |
67 | | class HL1DataBuffer { |
68 | | public: |
69 | | /** \brief Construct an empty buffer (null view). */ |
70 | 3 | HL1DataBuffer() AI_NO_EXCEPT : data_(nullptr), |
71 | 3 | length_(0), |
72 | 3 | owner_(nullptr) {} |
73 | | |
74 | | /** \brief Non-copyable (buffer may own memory). */ |
75 | | HL1DataBuffer(const HL1DataBuffer &) = delete; |
76 | | |
77 | | /** \brief Non-copyable (buffer may own memory). */ |
78 | | HL1DataBuffer &operator=(const HL1DataBuffer &) = delete; |
79 | | |
80 | | /** \brief Move-construct, transferring ownership/view state. */ |
81 | 0 | HL1DataBuffer(HL1DataBuffer &&other) AI_NO_EXCEPT : data_(other.data_), |
82 | 0 | length_(other.length_), |
83 | 0 | owner_(std::move(other.owner_)) { |
84 | 0 | other.data_ = nullptr; |
85 | 0 | other.length_ = 0; |
86 | 0 | other.owner_ = nullptr; |
87 | 0 | } |
88 | | |
89 | | /** \brief Move-assign, transferring ownership/view state. */ |
90 | 1 | HL1DataBuffer &operator=(HL1DataBuffer &&other) AI_NO_EXCEPT { |
91 | 1 | if (this != &other) { |
92 | 1 | data_ = other.data_; |
93 | 1 | length_ = other.length_; |
94 | 1 | owner_ = std::move(other.owner_); |
95 | | |
96 | 1 | other.data_ = nullptr; |
97 | 1 | other.length_ = 0; |
98 | 1 | other.owner_ = nullptr; |
99 | 1 | } |
100 | | |
101 | 1 | return *this; |
102 | 1 | } |
103 | | |
104 | | /** |
105 | | * \brief Create a non-owning view into external bytes. |
106 | | * |
107 | | * \param[in] data Pointer to raw bytes (must outlive the view). |
108 | | * \param[in] length Size in bytes. |
109 | | */ |
110 | 1 | static HL1DataBuffer view(const unsigned char *data, size_t length) { |
111 | 1 | HL1DataBuffer b; |
112 | 1 | b.data_ = data; |
113 | 1 | b.length_ = length; |
114 | 1 | b.owner_ = nullptr; |
115 | 1 | return b; |
116 | 1 | } |
117 | | |
118 | | /** |
119 | | * \brief Create a non-owning view of another buffer. |
120 | | * |
121 | | * \param[in] other Source buffer. |
122 | | */ |
123 | 1 | static HL1DataBuffer view(const HL1DataBuffer &other) { |
124 | 1 | HL1DataBuffer b; |
125 | 1 | b.data_ = other.data_; |
126 | 1 | b.length_ = other.length_; |
127 | 1 | b.owner_ = nullptr; |
128 | 1 | return b; |
129 | 1 | } |
130 | | |
131 | | /** |
132 | | * \brief Create an owning buffer by taking ownership of allocated storage. |
133 | | * |
134 | | * \param[in] buffer Unique buffer storage. |
135 | | * \param[in] length Size in bytes. |
136 | | */ |
137 | 0 | static HL1DataBuffer owning(std::unique_ptr<unsigned char[]> buffer, size_t length) { |
138 | 0 | HL1DataBuffer b; |
139 | 0 | b.data_ = buffer.get(); |
140 | 0 | b.length_ = length; |
141 | 0 | b.owner_ = std::move(buffer); |
142 | 0 | return b; |
143 | 0 | } |
144 | | |
145 | | /** |
146 | | * \brief Return a typed pointer into the buffer with bounds checks. |
147 | | * |
148 | | * \param[in] offset Byte offset from the start of the buffer. |
149 | | * \param[in] elements Number of elements to access. |
150 | | * \return Pointer to the requested typed data inside the buffer. |
151 | | * \throws DeadlyImportError if the request is out of range. |
152 | | */ |
153 | | template <typename DataType> |
154 | 27 | const DataType *get_data(int offset, int elements) const { |
155 | 27 | if (offset < 0 || elements < 0) { |
156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); |
157 | 0 | } |
158 | | |
159 | 27 | const size_t uoffset = static_cast<size_t>(offset); |
160 | 27 | const size_t uelements = static_cast<size_t>(elements); |
161 | | |
162 | 27 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { |
163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); |
164 | 0 | } |
165 | | |
166 | 27 | return reinterpret_cast<const DataType *>(data_ + uoffset); |
167 | 27 | } Assimp::MDL::HalfLife::Header_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::Header_HL1>(int, int) const Line | Count | Source | 154 | 2 | const DataType *get_data(int offset, int elements) const { | 155 | 2 | if (offset < 0 || elements < 0) { | 156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 157 | 0 | } | 158 | | | 159 | 2 | const size_t uoffset = static_cast<size_t>(offset); | 160 | 2 | const size_t uelements = static_cast<size_t>(elements); | 161 | | | 162 | 2 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { | 163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 164 | 0 | } | 165 | | | 166 | 2 | return reinterpret_cast<const DataType *>(data_ + uoffset); | 167 | 2 | } |
Unexecuted instantiation: Assimp::MDL::HalfLife::SequenceHeader_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::SequenceHeader_HL1>(int, int) const Assimp::MDL::HalfLife::Texture_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::Texture_HL1>(int, int) const Line | Count | Source | 154 | 2 | const DataType *get_data(int offset, int elements) const { | 155 | 2 | if (offset < 0 || elements < 0) { | 156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 157 | 0 | } | 158 | | | 159 | 2 | const size_t uoffset = static_cast<size_t>(offset); | 160 | 2 | const size_t uelements = static_cast<size_t>(elements); | 161 | | | 162 | 2 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { | 163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 164 | 0 | } | 165 | | | 166 | 2 | return reinterpret_cast<const DataType *>(data_ + uoffset); | 167 | 2 | } |
unsigned char const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<unsigned char>(int, int) const Line | Count | Source | 154 | 4 | const DataType *get_data(int offset, int elements) const { | 155 | 4 | if (offset < 0 || elements < 0) { | 156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 157 | 0 | } | 158 | | | 159 | 4 | const size_t uoffset = static_cast<size_t>(offset); | 160 | 4 | const size_t uelements = static_cast<size_t>(elements); | 161 | | | 162 | 4 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { | 163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 164 | 0 | } | 165 | | | 166 | 4 | return reinterpret_cast<const DataType *>(data_ + uoffset); | 167 | 4 | } |
short const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<short>(int, int) const Line | Count | Source | 154 | 1 | const DataType *get_data(int offset, int elements) const { | 155 | 1 | if (offset < 0 || elements < 0) { | 156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 157 | 0 | } | 158 | | | 159 | 1 | const size_t uoffset = static_cast<size_t>(offset); | 160 | 1 | const size_t uelements = static_cast<size_t>(elements); | 161 | | | 162 | 1 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { | 163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 164 | 0 | } | 165 | | | 166 | 1 | return reinterpret_cast<const DataType *>(data_ + uoffset); | 167 | 1 | } |
Assimp::MDL::HalfLife::Bone_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::Bone_HL1>(int, int) const Line | Count | Source | 154 | 2 | const DataType *get_data(int offset, int elements) const { | 155 | 2 | if (offset < 0 || elements < 0) { | 156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 157 | 0 | } | 158 | | | 159 | 2 | const size_t uoffset = static_cast<size_t>(offset); | 160 | 2 | const size_t uelements = static_cast<size_t>(elements); | 161 | | | 162 | 2 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { | 163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 164 | 0 | } | 165 | | | 166 | 2 | return reinterpret_cast<const DataType *>(data_ + uoffset); | 167 | 2 | } |
Assimp::MDL::HalfLife::Bodypart_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::Bodypart_HL1>(int, int) const Line | Count | Source | 154 | 3 | const DataType *get_data(int offset, int elements) const { | 155 | 3 | if (offset < 0 || elements < 0) { | 156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 157 | 0 | } | 158 | | | 159 | 3 | const size_t uoffset = static_cast<size_t>(offset); | 160 | 3 | const size_t uelements = static_cast<size_t>(elements); | 161 | | | 162 | 3 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { | 163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 164 | 0 | } | 165 | | | 166 | 3 | return reinterpret_cast<const DataType *>(data_ + uoffset); | 167 | 3 | } |
Assimp::MDL::HalfLife::Model_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::Model_HL1>(int, int) const Line | Count | Source | 154 | 3 | const DataType *get_data(int offset, int elements) const { | 155 | 3 | if (offset < 0 || elements < 0) { | 156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 157 | 0 | } | 158 | | | 159 | 3 | const size_t uoffset = static_cast<size_t>(offset); | 160 | 3 | const size_t uelements = static_cast<size_t>(elements); | 161 | | | 162 | 3 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { | 163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 164 | 0 | } | 165 | | | 166 | 3 | return reinterpret_cast<const DataType *>(data_ + uoffset); | 167 | 3 | } |
Assimp::MDL::HalfLife::Mesh_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::Mesh_HL1>(int, int) const Line | Count | Source | 154 | 1 | const DataType *get_data(int offset, int elements) const { | 155 | 1 | if (offset < 0 || elements < 0) { | 156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 157 | 0 | } | 158 | | | 159 | 1 | const size_t uoffset = static_cast<size_t>(offset); | 160 | 1 | const size_t uelements = static_cast<size_t>(elements); | 161 | | | 162 | 1 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { | 163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 164 | 0 | } | 165 | | | 166 | 1 | return reinterpret_cast<const DataType *>(data_ + uoffset); | 167 | 1 | } |
float const (*Assimp::MDL::HalfLife::HL1DataBuffer::get_data<float [3]>(int, int) const) [3] Line | Count | Source | 154 | 2 | const DataType *get_data(int offset, int elements) const { | 155 | 2 | if (offset < 0 || elements < 0) { | 156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 157 | 0 | } | 158 | | | 159 | 2 | const size_t uoffset = static_cast<size_t>(offset); | 160 | 2 | const size_t uelements = static_cast<size_t>(elements); | 161 | | | 162 | 2 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { | 163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 164 | 0 | } | 165 | | | 166 | 2 | return reinterpret_cast<const DataType *>(data_ + uoffset); | 167 | 2 | } |
Assimp::MDL::HalfLife::SequenceDesc_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::SequenceDesc_HL1>(int, int) const Line | Count | Source | 154 | 3 | const DataType *get_data(int offset, int elements) const { | 155 | 3 | if (offset < 0 || elements < 0) { | 156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 157 | 0 | } | 158 | | | 159 | 3 | const size_t uoffset = static_cast<size_t>(offset); | 160 | 3 | const size_t uelements = static_cast<size_t>(elements); | 161 | | | 162 | 3 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { | 163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 164 | 0 | } | 165 | | | 166 | 3 | return reinterpret_cast<const DataType *>(data_ + uoffset); | 167 | 3 | } |
Assimp::MDL::HalfLife::SequenceGroup_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::SequenceGroup_HL1>(int, int) const Line | Count | Source | 154 | 2 | const DataType *get_data(int offset, int elements) const { | 155 | 2 | if (offset < 0 || elements < 0) { | 156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 157 | 0 | } | 158 | | | 159 | 2 | const size_t uoffset = static_cast<size_t>(offset); | 160 | 2 | const size_t uelements = static_cast<size_t>(elements); | 161 | | | 162 | 2 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { | 163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 164 | 0 | } | 165 | | | 166 | 2 | return reinterpret_cast<const DataType *>(data_ + uoffset); | 167 | 2 | } |
Assimp::MDL::HalfLife::AnimValueOffset_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::AnimValueOffset_HL1>(int, int) const Line | Count | Source | 154 | 1 | const DataType *get_data(int offset, int elements) const { | 155 | 1 | if (offset < 0 || elements < 0) { | 156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 157 | 0 | } | 158 | | | 159 | 1 | const size_t uoffset = static_cast<size_t>(offset); | 160 | 1 | const size_t uelements = static_cast<size_t>(elements); | 161 | | | 162 | 1 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { | 163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 164 | 0 | } | 165 | | | 166 | 1 | return reinterpret_cast<const DataType *>(data_ + uoffset); | 167 | 1 | } |
Unexecuted instantiation: Assimp::MDL::HalfLife::AnimEvent_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::AnimEvent_HL1>(int, int) const Unexecuted instantiation: Assimp::MDL::HalfLife::Attachment_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::Attachment_HL1>(int, int) const Assimp::MDL::HalfLife::Hitbox_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::Hitbox_HL1>(int, int) const Line | Count | Source | 154 | 1 | const DataType *get_data(int offset, int elements) const { | 155 | 1 | if (offset < 0 || elements < 0) { | 156 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 157 | 0 | } | 158 | | | 159 | 1 | const size_t uoffset = static_cast<size_t>(offset); | 160 | 1 | const size_t uelements = static_cast<size_t>(elements); | 161 | | | 162 | 1 | if (uoffset > length_ || uelements > (length_ - uoffset) / sizeof(DataType)) { | 163 | 0 | throw DeadlyImportError("MDL file contains invalid data"); | 164 | 0 | } | 165 | | | 166 | 1 | return reinterpret_cast<const DataType *>(data_ + uoffset); | 167 | 1 | } |
Unexecuted instantiation: Assimp::MDL::HalfLife::BoneController_HL1 const* Assimp::MDL::HalfLife::HL1DataBuffer::get_data<Assimp::MDL::HalfLife::BoneController_HL1>(int, int) const |
168 | | |
169 | | private: |
170 | | /** Raw byte pointer (points to owner_.get() when owning, otherwise external). */ |
171 | | const unsigned char *data_; |
172 | | /** Buffer length in bytes. */ |
173 | | size_t length_; |
174 | | /** Owning storage (null for views). */ |
175 | | std::unique_ptr<unsigned char[]> owner_; |
176 | | }; |
177 | | |
178 | | } // namespace HalfLife |
179 | | } // namespace MDL |
180 | | } // namespace Assimp |
181 | | |
182 | | #endif // AI_HL1DATABUFFER_INCLUDED |