1
2 //
3 // This source file is part of appleseed.
4 // Visit https://appleseedhq.net/ for additional information and resources.
5 //
6 // This software is released under the MIT license.
7 //
8 // Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
9 // Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 // THE SOFTWARE.
28 //
29
30 #pragma once
31
32 // appleseed.main headers.
33 #include "main/dllsymbol.h"
34
35 // Standard headers.
36 #include <algorithm>
37 #include <cassert>
38 #include <cstddef>
39 #include <cstring>
40 #include <iterator>
41 #include <vector>
42
43 namespace foundation
44 {
45
46 //
47 // A minimalist array class that can safely cross DLL boundaries.
48 //
49
50 #define APPLESEED_DECLARE_APIARRAY(ArrayName, ArrayType) \
51 class APPLESEED_DLLSYMBOL ArrayName \
52 { \
53 public: \
54 /* Types. */ \
55 typedef ArrayType value_type; \
56 typedef value_type& reference; \
57 typedef const value_type& const_reference; \
58 typedef size_t size_type; \
59 \
60 /* Constructors. */ \
61 ArrayName(); \
62 ArrayName(const ArrayName& rhs); \
63 ArrayName( \
64 const size_type size, \
65 const value_type* values); \
66 \
67 /* Destructor. */ \
68 ~ArrayName(); \
69 \
70 /* Assignment operator. */ \
71 ArrayName& operator=(const ArrayName& rhs); \
72 \
73 /* Comparison operators. */ \
74 bool operator==(const ArrayName& rhs) const; \
75 bool operator!=(const ArrayName& rhs) const; \
76 \
77 /* Returns the size of the vector. */ \
78 size_type size() const; \
79 \
80 /* Tests if the vector is empty. */ \
81 bool empty() const; \
82 \
83 /* Clears the vector. */ \
84 void clear(); \
85 \
86 /* Reserves memory for a given number of elements. */ \
87 void reserve(const size_type count); \
88 \
89 /* Specifies a new size for a vector. */ \
90 void resize(const size_type new_size); \
91 \
92 /* Adds an element to the end of the vector. */ \
93 void push_back(const value_type& val); \
94 \
95 /* Append a vector to the end of the vector. */ \
96 void append(const ArrayName& rhs); \
97 \
98 /* Returns the vector element at a specified position. */ \
99 reference operator[](const size_type pos); \
100 const_reference operator[](const size_type pos) const; \
101 \
102 private: \
103 /* Private implementation. */ \
104 struct Impl; \
105 Impl* impl; \
106 }
107
108 #define APPLESEED_DEFINE_APIARRAY(ArrayName) \
109 struct ArrayName::Impl \
110 : public std::vector<value_type> \
111 { \
112 }; \
113 \
114 ArrayName::ArrayName() \
115 : impl(new Impl()) \
116 { \
117 } \
118 \
119 ArrayName::ArrayName(const ArrayName& rhs) \
120 : impl(new Impl(*rhs.impl)) \
121 { \
122 } \
123 \
124 ArrayName::ArrayName( \
125 const size_type size, \
126 const value_type* values) \
127 : impl(new Impl()) \
128 { \
129 assert(size > 0); \
130 assert(values); \
131 impl->reserve(size); \
132 std::copy(values, values + size, std::back_inserter(*impl)); \
133 } \
134 \
135 ArrayName::~ArrayName() \
136 { \
137 delete impl; \
138 } \
139 \
140 ArrayName& ArrayName::operator=(const ArrayName& rhs) \
141 { \
142 *impl = *rhs.impl; \
143 return *this; \
144 } \
145 \
146 bool ArrayName::operator==(const ArrayName& rhs) const \
147 { \
148 return *impl == *rhs.impl; \
149 } \
150 \
151 bool ArrayName::operator!=(const ArrayName& rhs) const \
152 { \
153 return *impl != *rhs.impl; \
154 } \
155 \
156 ArrayName::size_type ArrayName::size() const \
157 { \
158 return impl->size(); \
159 } \
160 \
161 bool ArrayName::empty() const \
162 { \
163 return impl->empty(); \
164 } \
165 \
166 void ArrayName::clear() \
167 { \
168 impl->clear(); \
169 } \
170 \
171 void ArrayName::reserve(const size_type count) \
172 { \
173 impl->reserve(count); \
174 } \
175 \
176 void ArrayName::resize(const size_type new_size) \
177 { \
178 impl->resize(new_size); \
179 } \
180 \
181 void ArrayName::push_back(const value_type& val) \
182 { \
183 impl->push_back(val); \
184 } \
185 \
186 void ArrayName::append(const ArrayName& rhs) \
187 { \
188 impl->insert(impl->end(), rhs.impl->begin(), rhs.impl->end()); \
189 } \
190 \
191 ArrayName::reference \
192 ArrayName::operator[](const size_type pos) \
193 { \
194 return (*impl)[pos]; \
195 } \
196 \
197 ArrayName::const_reference \
198 ArrayName::operator[](const size_type pos) const \
199 { \
200 return (*impl)[pos]; \
201 }
202
203
204 //
205 // Utility function to convert between an array and a std::vector (works both ways).
206 //
207
208 template <typename U, typename V>
array_vector(const V & v)209 U array_vector(const V& v)
210 {
211 const size_t n = v.size();
212
213 U u;
214 u.reserve(n);
215
216 for (size_t i = 0; i < n; ++i)
217 u.push_back(v[i]);
218
219 return u;
220 }
221
222 } // namespace foundation
223