Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
sdl_helpers.ipp
Go to the documentation of this file.
1#pragma once
2
3#include "SDL/sdl_helpers.h"
4#include "Math/TVector2.h"
5#include "Math/TVector3.h"
6#include "Math/TVector4.h"
7#include "Math/TQuaternion.h"
8#include "SDL/Tokenizer.h"
9#include "SDL/sdl_traits.h"
10#include "SDL/sdl_exceptions.h"
11#include "SDL/ISdlResource.h"
12
13#include <Common/assertion.h>
14#include <Common/Utility/string_utils.h>
15
16#include <type_traits>
17#include <algorithm>
18#include <exception>
19
20namespace ph::sdl
21{
22
23template<typename FloatType>
24inline FloatType load_float(std::string_view sdlFloatStr)
25{
26 try
27 {
28 return string_utils::parse_float<FloatType>(sdlFloatStr);
29 }
30 catch(const std::exception& e)
31 {
32 throw SdlLoadError("on loading floating-point value -> " + std::string(e.what()));
33 }
34}
35
36template<typename IntType>
37inline IntType load_int(std::string_view sdlIntStr)
38{
39 try
40 {
41 return string_utils::parse_int<IntType>(sdlIntStr);
42 }
43 catch(const std::exception& e)
44 {
45 throw SdlLoadError("on loading integer value -> " + std::string(e.what()));
46 }
47}
48
49template<typename NumberType>
50inline NumberType load_number(std::string_view sdlNumberStr)
51{
52 if constexpr(std::is_floating_point_v<NumberType>)
53 {
54 return load_float<NumberType>(sdlNumberStr);
55 }
56 else
57 {
58 static_assert(std::is_integral_v<NumberType>);
59
60 return load_int<NumberType>(sdlNumberStr);
61 }
62}
63
64template<typename NumberType, std::size_t EXTENT>
65inline void load_numbers(std::string_view sdlNumbersStr, TSpan<NumberType, EXTENT> out_numbers)
66{
67 static const Tokenizer tokenizer({' ', '\t', '\n', '\r'}, {});
68
69 const auto N = out_numbers.size();
70 PH_ASSERT_GT(N, 0);
71
72 try
73 {
74 // TODO: use view
75 std::vector<std::string> tokens;
76 tokenizer.tokenize(std::string(sdlNumbersStr), tokens);
77
78 // N input values form a N-tuple exactly
79 if(tokens.size() == N)
80 {
81 for(std::size_t ni = 0; ni < N; ++ni)
82 {
83 out_numbers[ni] = load_number<NumberType>(tokens[ni]);
84 }
85 }
86 // 1 input value results in the N-tuple filled with the same value
87 else if(tokens.size() == 1)
88 {
89 std::fill(out_numbers.begin(), out_numbers.end(), load_number<NumberType>(tokens[0]));
90 }
91 else
92 {
93 throw_formatted<SdlLoadError>(
94 "invalid number of tokens: {}", tokens.size());
95 }
96 }
97 catch(const SdlException& e)
98 {
99 throw_formatted<SdlLoadError>(
100 "on parsing {}-tuple -> {}", out_numbers.size(), e.whatStr());
101 }
102}
103
104inline real load_real(std::string_view sdlRealStr)
105{
106 return load_float<real>(sdlRealStr);
107}
108
109inline integer load_integer(std::string_view sdlIntegerStr)
110{
111 return load_int<integer>(sdlIntegerStr);
112}
113
114template<typename Element>
115inline math::TVector2<Element> load_vector2(std::string_view sdlVec2Str)
116{
117 try
118 {
120 load_numbers(sdlVec2Str, vec2.toSpan());
121 return vec2;
122 }
123 catch(const SdlException& e)
124 {
125 throw SdlLoadError("on parsing Vector2 -> " + e.whatStr());
126 }
127}
128
129template<typename Element>
130inline math::TVector3<Element> load_vector3(std::string_view sdlVec3Str)
131{
132 try
133 {
135 load_numbers(sdlVec3Str, vec3.toSpan());
136 return vec3;
137 }
138 catch(const SdlException& e)
139 {
140 throw SdlLoadError("on parsing Vector3 -> " + e.whatStr());
141 }
142}
143
144template<typename Element>
145inline math::TVector4<Element> load_vector4(std::string_view sdlVec4Str)
146{
147 try
148 {
150 load_numbers(sdlVec4Str, vec4.toSpan());
151 return vec4;
152 }
153 catch(const SdlException& e)
154 {
155 throw SdlLoadError("on parsing Vector4 -> " + e.whatStr());
156 }
157}
158
159template<typename Element>
160inline math::TQuaternion<Element> load_quaternion(std::string_view sdlQuatStr)
161{
162 try
163 {
165 load_numbers(sdlQuatStr, quat.toSpan());
166 return quat;
167 }
168 catch(const SdlException& e)
169 {
170 throw SdlLoadError("on parsing Quaternion -> " + e.whatStr());
171 }
172}
173
174template<typename NumberType>
175inline std::vector<NumberType> load_number_array(std::string_view sdlNumberArrayStr)
176{
177 static const Tokenizer tokenizer({' ', '\t', '\n', '\r'}, {});
178
179 try
180 {
181 // TODO: use view
182 std::vector<std::string> arrayTokens;
183 tokenizer.tokenize(std::string(sdlNumberArrayStr), arrayTokens);
184
185 std::vector<NumberType> numberArray(arrayTokens.size());
186 for(std::size_t i = 0; i < numberArray.size(); ++i)
187 {
188 numberArray[i] = load_number<NumberType>(arrayTokens[i]);
189 }
190
191 return numberArray;
192 }
193 catch(const SdlException& e)
194 {
195 throw SdlLoadError("on parsing number array -> " + e.whatStr());
196 }
197}
198
199template<typename Element>
200inline std::vector<math::TVector3<Element>> load_vector3_array(std::string_view sdlVec3ArrayStr)
201{
202 static const Tokenizer tokenizer({' ', '\t', '\n', '\r'}, {{'"', '"'}});
203
204 try
205 {
206 // TODO: use view
207 std::vector<std::string> vec3Tokens;
208 tokenizer.tokenize(std::string(sdlVec3ArrayStr), vec3Tokens);
209
210 std::vector<math::TVector3<Element>> vec3Array(vec3Tokens.size());
211 for(std::size_t i = 0; i < vec3Array.size(); ++i)
212 {
213 vec3Array[i] = load_vector3<Element>(vec3Tokens[i]);
214 }
215
216 return vec3Array;
217 }
218 catch(const SdlException& e)
219 {
220 throw SdlLoadError("on parsing Vector3 array -> " + e.whatStr());
221 }
222}
223
224inline void save_real(const real value, std::string& out_str)
225{
226 save_float<real>(value, out_str);
227}
228
229inline void save_integer(const integer value, std::string& out_str)
230{
231 save_int<integer>(value, out_str);
232}
233
234template<typename FloatType>
235inline void save_float(const FloatType value, std::string& out_str)
236{
237 try
238 {
239 string_utils::stringify_number(value, out_str, 32);
240 }
241 catch(const std::exception& e)
242 {
243 throw SdlSaveError("on saving floating-point value -> " + std::string(e.what()));
244 }
245}
246
247template<typename IntType>
248inline void save_int(const IntType value, std::string& out_str)
249{
250 try
251 {
252 string_utils::stringify_number(value, out_str, 32);
253 }
254 catch(const std::exception& e)
255 {
256 throw SdlSaveError("on saving integer value -> " + std::string(e.what()));
257 }
258}
259
260template<typename NumberType>
261inline void save_number(const NumberType value, std::string& out_str)
262{
263 if constexpr(std::is_floating_point_v<NumberType>)
264 {
265 save_float(value, out_str);
266 }
267 else
268 {
269 static_assert(std::is_integral_v<NumberType>);
270
271 save_int(value, out_str);
272 }
273}
274
275template<typename NumberType, std::size_t EXTENT>
276inline void save_numbers(
278 std::string& out_str)
279{
280 const auto N = numbers.size();
281 PH_ASSERT_GT(N, 0);
282
283 try
284 {
285 // If all values are equal, we can save it as one value
286 if(std::equal(numbers.begin() + 1, numbers.end(), numbers.begin()))
287 {
288 save_number<NumberType>(numbers[0], out_str);
289 }
290 else
291 {
292 save_number<NumberType>(numbers[0], out_str);
293 for(std::size_t ni = 1; ni < N; ++ni)
294 {
295 out_str += ' ';
296 save_number<NumberType>(numbers[ni], out_str);
297 }
298 }
299 }
300 catch(const SdlException& e)
301 {
302 throw_formatted<SdlSaveError>(
303 "on saving {}-tuple -> {}", numbers.size(), e.whatStr());
304 }
305}
306
307template<typename Element>
308inline void save_vector2(const math::TVector2<Element>& value, std::string& out_str)
309{
310 try
311 {
312 out_str += '"';
313 save_numbers(value.toView(), out_str);
314 out_str += '"';
315 }
316 catch(const SdlException& e)
317 {
318 throw SdlSaveError("on saving Vector2 -> " + e.whatStr());
319 }
320}
321
322template<typename Element>
323inline void save_vector3(const math::TVector3<Element>& value, std::string& out_str)
324{
325 try
326 {
327 out_str += '"';
328 save_numbers(value.toView(), out_str);
329 out_str += '"';
330 }
331 catch(const SdlException& e)
332 {
333 throw SdlSaveError("on saving Vector3 -> " + e.whatStr());
334 }
335}
336
337template<typename Element>
338inline void save_vector4(const math::TVector4<Element>& value, std::string& out_str)
339{
340 try
341 {
342 out_str += '"';
343 save_numbers(value.toView(), out_str);
344 out_str += '"';
345 }
346 catch(const SdlException& e)
347 {
348 throw SdlSaveError("on saving Vector4 -> " + e.whatStr());
349 }
350}
351
352template<typename Element>
353inline void save_quaternion(const math::TQuaternion<Element>& value, std::string& out_str)
354{
355 try
356 {
357 out_str += '"';
358 save_numbers(value.toView(), out_str);
359 out_str += '"';
360 }
361 catch(const SdlException& e)
362 {
363 throw SdlSaveError("on saving Quaternion -> " + e.whatStr());
364 }
365}
366
367template<typename NumberType>
368inline void save_number_array(TSpanView<NumberType> values, std::string& out_str)
369{
370 try
371 {
372 out_str += '"';
373 save_numbers(values, out_str);
374 out_str += '"';
375 }
376 catch(const SdlException& e)
377 {
378 throw SdlSaveError("on saving number array -> " + e.whatStr());
379 }
380}
381
382template<typename Element>
383inline void save_vector3_array(TSpanView<math::TVector3<Element>> values, std::string& out_str)
384{
385 try
386 {
387 out_str += '{';
388
389 if(!values.empty())
390 {
391 save_vector3(values[0], out_str);
392 }
393
394 for(std::size_t vi = 1; vi < values.size(); ++vi)
395 {
396 out_str += ' ';
397 save_vector3(values[vi], out_str);
398 }
399
400 out_str += '}';
401 }
402 catch(const SdlException& e)
403 {
404 throw SdlSaveError("on saving Vector3 array -> " + e.whatStr());
405 }
406}
407
408template<typename T>
410{
412 {
413 return T::CATEGORY;
414 }
415 else
416 {
418 }
419}
420
421template<std::integral IntType>
422inline constexpr ESdlDataType int_type_of()
423{
424 if constexpr(CSame<IntType, bool>)
425 {
426 return ESdlDataType::Bool;
427 }
428 else if constexpr(CSame<IntType, int8>)
429 {
430 return ESdlDataType::Int8;
431 }
432 else if constexpr(CSame<IntType, uint8>)
433 {
434 return ESdlDataType::UInt8;
435 }
436 else if constexpr(CSame<IntType, int16>)
437 {
438 return ESdlDataType::Int16;
439 }
440 else if constexpr(CSame<IntType, uint16>)
441 {
443 }
444 else if constexpr(CSame<IntType, int32>)
445 {
446 return ESdlDataType::Int32;
447 }
448 else if constexpr(CSame<IntType, uint32>)
449 {
451 }
452 else if constexpr(CSame<IntType, int64>)
453 {
454 return ESdlDataType::Int64;
455 }
456 else
457 {
458 static_assert(CSame<IntType, uint64>);
460 }
461}
462
463template<std::floating_point FloatType>
464inline constexpr ESdlDataType float_type_of()
465{
466 if constexpr(CSame<FloatType, float32>)
467 {
469 }
470 else
471 {
472 static_assert(CSame<FloatType, float64>);
474 }
475}
476
477template<CNumber NumberType>
478inline constexpr ESdlDataType number_type_of()
479{
480 if constexpr(std::is_floating_point_v<NumberType>)
481 {
483 }
484 else
485 {
486 static_assert(std::is_integral_v<NumberType>);
488 }
489}
490
491template<typename T>
493{
494 constexpr ESdlTypeCategory CATEGORY = sdl::category_of<T>();
495
496 if constexpr(CATEGORY == ESdlTypeCategory::Ref_Geometry)
497 {
499 }
500 else if constexpr(CATEGORY == ESdlTypeCategory::Ref_Material)
501 {
503 }
504 else if constexpr(CATEGORY == ESdlTypeCategory::Ref_Motion)
505 {
507 }
508 else if constexpr(CATEGORY == ESdlTypeCategory::Ref_Actor)
509 {
510 return ESdlDataType::Actor;
511 }
512 else if constexpr(CATEGORY == ESdlTypeCategory::Ref_Image)
513 {
514 return ESdlDataType::Image;
515 }
516 else if constexpr(CATEGORY == ESdlTypeCategory::Ref_FrameProcessor)
517 {
519 }
520 else if constexpr(CATEGORY == ESdlTypeCategory::Ref_Observer)
521 {
523 }
524 else if constexpr(CATEGORY == ESdlTypeCategory::Ref_SampleSource)
525 {
527 }
528 else if constexpr(CATEGORY == ESdlTypeCategory::Ref_Visualizer)
529 {
531 }
532 else if constexpr(CATEGORY == ESdlTypeCategory::Ref_Option)
533 {
535 }
536 else if constexpr(CATEGORY == ESdlTypeCategory::Ref_Object)
537 {
539 }
540 else
541 {
542 static_assert(CATEGORY == ESdlTypeCategory::Unspecified);
543
544 return ESdlDataType::None;
545 }
546}
547
548template<typename DstType, typename SrcType>
549inline DstType* cast_to(SrcType* const srcResource)
550{
551 // `SrcType` and `DstType` are both possibly cv-qualified
552
553 static_assert(std::is_base_of_v<ISdlResource, SrcType>,
554 "Source resource must derive from ISdlResource.");
555
556 static_assert(std::is_base_of_v<ISdlResource, DstType>,
557 "Casted-to type must derive from ISdlResource.");
558
559 if(srcResource == nullptr)
560 {
561 throw SdlException("source resource is empty");
562 }
563
564 DstType* const dstResource = dynamic_cast<DstType*>(srcResource);
565 if(dstResource == nullptr)
566 {
567 throw_formatted<SdlException>(
568 "type cast error: source resource cannot be casted to the specified type (resource ID: {})",
569 srcResource->getId());
570 }
571
572 return dstResource;
573}
574
575}// end namespace ph::sdl
General exception thrown on error related to SDL.
Definition sdl_exceptions.h:13
Error on the SDL input process.
Definition sdl_exceptions.h:22
Error on the SDL output process.
Definition sdl_exceptions.h:30
Definition Tokenizer.h:13
void tokenize(const std::string &source, std::vector< std::string > &out_results) const
Definition Tokenizer.cpp:25
TSpanView< T, N > toView() const
Definition TArithmeticArrayBase.ipp:869
TSpan< T, N > toSpan()
Definition TArithmeticArrayBase.ipp:862
Represents a quaternion.
Definition TQuaternion.h:17
Represents a 2-D vector.
Definition TVector2.h:19
Represents a 3-D vector.
Definition TVector3.h:17
Represents a 4-D vector.
Definition TVector4.h:15
TSpanView< T, N > toView() const
Definition TArithmeticArrayBase.ipp:869
TSpan< T, N > toSpan()
Definition TArithmeticArrayBase.ipp:862
Check if SDL category information can be obtained statically. The result is true if the static member...
Definition sdl_traits.h:20
Definition traits.h:113
Definition sdl_traits.h:13
Definition sdl_spectrum_io.cpp:17
void save_vector3(const math::TVector3< Element > &value, std::string &out_str)
Definition sdl_helpers.ipp:323
integer load_integer(std::string_view sdlIntegerStr)
Definition sdl_helpers.ipp:109
IntType load_int(std::string_view sdlIntStr)
Returns a integer number by processing its SDL representation. Supports ph::integer and all signed an...
Definition sdl_helpers.ipp:37
void save_number_array(TSpanView< NumberType > values, std::string &out_str)
Definition sdl_helpers.ipp:368
void save_int(IntType value, std::string &out_str)
Converts a integer number to its SDL representation. Supports ph::real, float, double,...
Definition sdl_helpers.ipp:248
void load_numbers(std::string_view sdlNumbersStr, TSpan< NumberType, EXTENT > out_numbers)
Definition sdl_helpers.ipp:65
NumberType load_number(std::string_view sdlNumberStr)
Returns a number by processing its SDL representation. Accepts all types supported by load_float() an...
Definition sdl_helpers.ipp:50
DstType * cast_to(SrcType *srcResource)
Cast between SDL resource types. Cast the input SDL resource instance of SrcType to an instance of Ds...
Definition sdl_helpers.ipp:549
void save_integer(integer value, std::string &out_str)
Definition sdl_helpers.ipp:229
std::vector< math::TVector3< Element > > load_vector3_array(std::string_view sdlVec3ArrayStr)
Definition sdl_helpers.ipp:200
void save_vector4(const math::TVector4< Element > &value, std::string &out_str)
Definition sdl_helpers.ipp:338
void save_quaternion(const math::TQuaternion< Element > &value, std::string &out_str)
Definition sdl_helpers.ipp:353
constexpr ESdlDataType int_type_of()
Definition sdl_helpers.ipp:422
void save_number(NumberType value, std::string &out_str)
Converts a number to its SDL representation. Accepts all types supported by save_float() and save_int...
Definition sdl_helpers.ipp:261
constexpr ESdlTypeCategory category_of()
Statically gets the SDL category of T.
Definition sdl_helpers.ipp:409
void save_numbers(TSpanView< NumberType, EXTENT > numbers, std::string &out_str)
Definition sdl_helpers.ipp:276
void save_float(FloatType value, std::string &out_str)
Converts a floating-point number to its SDL representation. Supports ph::real, float,...
Definition sdl_helpers.ipp:235
constexpr ESdlDataType resource_type_of()
Definition sdl_helpers.ipp:492
FloatType load_float(std::string_view sdlFloatStr)
Returns a floating-point number by processing its SDL representation. Supports ph::real,...
Definition sdl_helpers.ipp:24
void save_real(real value, std::string &out_str)
Definition sdl_helpers.ipp:224
math::TQuaternion< Element > load_quaternion(std::string_view sdlQuatStr)
Definition sdl_helpers.ipp:160
math::TVector4< Element > load_vector4(std::string_view sdlVec4Str)
Definition sdl_helpers.ipp:145
math::TVector2< Element > load_vector2(std::string_view sdlVec2Str)
Definition sdl_helpers.ipp:115
std::vector< NumberType > load_number_array(std::string_view sdlNumberArrayStr)
Definition sdl_helpers.ipp:175
void save_vector3_array(TSpanView< math::TVector3< Element > > values, std::string &out_str)
Definition sdl_helpers.ipp:383
constexpr ESdlDataType number_type_of()
Definition sdl_helpers.ipp:478
void save_vector2(const math::TVector2< Element > &value, std::string &out_str)
Definition sdl_helpers.ipp:308
constexpr ESdlDataType float_type_of()
Definition sdl_helpers.ipp:464
math::TVector3< Element > load_vector3(std::string_view sdlVec3Str)
Definition sdl_helpers.ipp:130
real load_real(std::string_view sdlRealStr)
Definition sdl_helpers.ipp:104
std::span< const T, EXTENT > TSpanView
Same as TSpan, except that the objects are const-qualified. Note that for pointer types,...
Definition TSpan.h:19
std::span< T, EXTENT > TSpan
A contiguous sequence of objects of type T. Effectively the same as std::span.
Definition TSpan.h:12
ESdlDataType
Common data types used by SDL. Each listed data type has some form of one to one mapping to a specifi...
Definition ESdlDataType.h:13
ESdlTypeCategory
Definition ESdlTypeCategory.h:15
Low-level helpers for SDL. Helpers are in an additional sdl namespace.