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