20#ifndef PLYWOOT_WRITER_HPP
21#define PLYWOOT_WRITER_HPP
32namespace plywoot::detail {
46template<
typename FormatWriterPolicy>
47class Writer :
private FormatWriterPolicy
50 using FormatWriterPolicy::FormatWriterPolicy;
55 void write(
const PlyElement &element,
const std::uint8_t *src, std::size_t alignment)
const
57 for (std::size_t i = 0; i < element.size(); ++i)
59 const std::vector<PlyProperty> &properties = element.properties();
60 const auto first = properties.begin();
61 const auto last = properties.end();
66 if (curr > first) { this->writeTokenSeparator(); }
68 const PlyProperty &
property = *curr++;
69 if (property.isList())
71 switch (property.type())
73 case PlyDataType::Char:
74 src = writeProperty(src, property, reflect::Type<std::vector<char>>{});
76 case PlyDataType::UChar:
77 src = writeProperty(src, property, reflect::Type<std::vector<unsigned char>>{});
79 case PlyDataType::Short:
80 src = writeProperty(src, property, reflect::Type<std::vector<short>>{});
82 case PlyDataType::UShort:
83 src = writeProperty(src, property, reflect::Type<std::vector<unsigned short>>{});
85 case PlyDataType::Int:
86 src = writeProperty(src, property, reflect::Type<std::vector<int>>{});
88 case PlyDataType::UInt:
89 src = writeProperty(src, property, reflect::Type<std::vector<unsigned int>>{});
91 case PlyDataType::Float:
92 src = writeProperty(src, property, reflect::Type<std::vector<float>>{});
94 case PlyDataType::Double:
95 src = writeProperty(src, property, reflect::Type<std::vector<double>>{});
101 switch (property.type())
103 case PlyDataType::Char:
104 src = writeProperty(src, property, reflect::Type<char>{});
106 case PlyDataType::UChar:
107 src = writeProperty(src, property, reflect::Type<unsigned char>{});
109 case PlyDataType::Short:
110 src = writeProperty(src, property, reflect::Type<short>{});
112 case PlyDataType::UShort:
113 src = writeProperty(src, property, reflect::Type<unsigned short>{});
115 case PlyDataType::Int:
116 src = writeProperty(src, property, reflect::Type<int>{});
118 case PlyDataType::UInt:
119 src = writeProperty(src, property, reflect::Type<unsigned int>{});
121 case PlyDataType::Float:
122 src = writeProperty(src, property, reflect::Type<float>{});
124 case PlyDataType::Double:
125 src = writeProperty(src, property, reflect::Type<double>{});
131 src = detail::align(src, alignment);
133 this->writeNewline();
137 template<
typename... Ts>
138 void write(
const PlyElement &element,
const reflect::Layout<Ts...> layout)
const
140 const auto first = element.properties().begin();
141 const auto last = element.properties().end();
143 const std::uint8_t *src = layout.data();
144 for (std::size_t i = 0; i < layout.size(); ++i)
146 src = detail::align(writeElement<Ts...>(src, first, last), layout.alignment());
151 template<
typename PlyT,
typename SrcT>
152 const std::uint8_t *writeProperty(
const std::uint8_t *src, reflect::Type<SrcT>)
const
154 if constexpr (std::is_arithmetic_v<SrcT>)
156 src =
static_cast<const std::uint8_t *
>(detail::align(src,
alignof(SrcT)));
157 this->writeNumber(
static_cast<PlyT
>(*
reinterpret_cast<const SrcT *
>(src)));
158 return src +
sizeof(SrcT);
160 else {
return static_cast<const std::uint8_t *
>(detail::align(src,
alignof(SrcT))) +
sizeof(SrcT); }
165 template<
typename PlyT,
typename SrcT, std::
size_t N>
166 const std::uint8_t *writeProperty(
const std::uint8_t *src, reflect::Type<reflect::Pack<SrcT, N>>)
const
168 static_assert(N > 0,
"invalid pack size specified (needs to be larger than zero)");
170 std::is_arithmetic<SrcT>::value,
"it is not (yet) possible to write packs of non-numeric types");
172 src =
static_cast<const std::uint8_t *
>(detail::align(src,
alignof(SrcT)));
173 this->
template writeNumbers<PlyT, SrcT>(
reinterpret_cast<const SrcT *
>(src), N);
174 return src + N *
sizeof(SrcT);
179 template<
typename SrcT>
180 const std::uint8_t *writeProperty(
const std::uint8_t *src, reflect::Type<reflect::Stride<SrcT>>)
const
182 return static_cast<const std::uint8_t *
>(detail::align(src,
alignof(SrcT))) +
sizeof(SrcT);
187 template<
typename PlyT,
typename PlySizeT,
typename SrcT, std::
size_t N>
188 const std::uint8_t *writeListProperty(
const std::uint8_t *src, reflect::Type<reflect::Array<SrcT, N>>)
const
190 static_assert(N > 0,
"invalid array size specified (needs to be larger than zero)");
192 src =
static_cast<const std::uint8_t *
>(detail::align(src,
alignof(SrcT)));
193 this->
template writeList<PlySizeT, PlyT, SrcT>(
reinterpret_cast<const SrcT *
>(src), N);
194 return src + N *
sizeof(SrcT);
198 template<
typename PlyT,
typename PlySizeT,
typename SrcT>
199 const std::uint8_t *writeListProperty(
const std::uint8_t *src, reflect::Type<std::vector<SrcT>>)
const
201 src =
static_cast<const std::uint8_t *
>(detail::align(src,
alignof(std::vector<SrcT>)));
202 const std::vector<SrcT> &v = *
reinterpret_cast<const std::vector<SrcT> *
>(src);
203 this->
template writeList<PlySizeT, PlyT, SrcT>(v.data(), v.size());
204 return src +
sizeof(std::vector<SrcT>);
207 template<
typename PlyT,
typename TypeTag>
208 const std::uint8_t *writeListProperty(
const std::uint8_t *src,
const PlyProperty &property, TypeTag tag)
211 switch (property.sizeType())
213 case PlyDataType::Char:
214 return writeListProperty<PlyT, char>(src, tag);
215 case PlyDataType::UChar:
216 return writeListProperty<PlyT, unsigned char>(src, tag);
217 case PlyDataType::Short:
218 return writeListProperty<PlyT, short>(src, tag);
219 case PlyDataType::UShort:
220 return writeListProperty<PlyT, unsigned short>(src, tag);
221 case PlyDataType::Int:
222 return writeListProperty<PlyT, int>(src, tag);
223 case PlyDataType::UInt:
224 return writeListProperty<PlyT, unsigned int>(src, tag);
225 case PlyDataType::Float:
226 return writeListProperty<PlyT, float>(src, tag);
227 case PlyDataType::Double:
228 return writeListProperty<PlyT, double>(src, tag);
234 template<
typename TypeTag>
235 const std::uint8_t *writeProperty(
const std::uint8_t *src,
const PlyProperty &property, TypeTag tag)
const
237 if constexpr (detail::isList<TypeTag>())
239 switch (property.type())
241 case PlyDataType::Char:
242 return writeListProperty<char>(src, property, tag);
243 case PlyDataType::UChar:
244 return writeListProperty<unsigned char>(src, property, tag);
245 case PlyDataType::Short:
246 return writeListProperty<short>(src, property, tag);
247 case PlyDataType::UShort:
248 return writeListProperty<unsigned short>(src, property, tag);
249 case PlyDataType::Int:
250 return writeListProperty<int>(src, property, tag);
251 case PlyDataType::UInt:
252 return writeListProperty<unsigned int>(src, property, tag);
253 case PlyDataType::Float:
254 return writeListProperty<float>(src, property, tag);
255 case PlyDataType::Double:
256 return writeListProperty<double>(src, property, tag);
261 switch (property.type())
263 case PlyDataType::Char:
264 return writeProperty<char>(src, tag);
265 case PlyDataType::UChar:
266 return writeProperty<unsigned char>(src, tag);
267 case PlyDataType::Short:
268 return writeProperty<short>(src, tag);
269 case PlyDataType::UShort:
270 return writeProperty<unsigned short>(src, tag);
271 case PlyDataType::Int:
272 return writeProperty<int>(src, tag);
273 case PlyDataType::UInt:
274 return writeProperty<unsigned int>(src, tag);
275 case PlyDataType::Float:
276 return writeProperty<float>(src, tag);
277 case PlyDataType::Double:
278 return writeProperty<double>(src, tag);
289 template<
typename SrcT>
290 const std::uint8_t *writeProperty(
291 const std::uint8_t *src,
292 PlyPropertyConstIterator first,
293 PlyPropertyConstIterator last)
const
295 return first < last ? writeProperty(src, *first, reflect::Type<SrcT>{})
296 : writeProperty(src, reflect::Type<reflect::Stride<SrcT>>{});
304 template<
typename Policy,
typename T>
305 const std::uint8_t *writeProperties(
306 const std::uint8_t *src,
307 PlyPropertyConstIterator first,
308 PlyPropertyConstIterator last)
const
310 return writeProperty<T>(src, first, last);
313 template<
typename Policy,
typename T,
typename U,
typename... Ts>
314 const std::uint8_t *writeProperties(
315 const std::uint8_t *src,
316 PlyPropertyConstIterator first,
317 PlyPropertyConstIterator last)
const
319 if constexpr (std::is_same_v<Policy, AsciiWriterPolicy>)
321 src = writeProperty<T>(src, first, last);
322 first += detail::numProperties<T>();
323 if (first < last) { this->writeTokenSeparator(); }
324 return writeProperties<Policy, U, Ts...>(src, first, last);
328 return writeProperties<Policy, U, Ts...>(
329 writeProperty<T>(src, first, last), first + detail::numProperties<T>(), last);
334 template<
typename... Ts>
335 const std::uint8_t *writeElement(
336 const std::uint8_t *src,
337 PlyPropertyConstIterator first,
338 PlyPropertyConstIterator last)
const
340 src = this->writeProperties<FormatWriterPolicy, Ts...>(src, first, last);
344 if (detail::numProperties<Ts...>() <
static_cast<std::size_t
>(std::distance(first, last)))
346 this->writeMissingProperties(first + detail::numProperties<Ts...>(), last);
349 this->writeNewline();