SUAPI-CppWrapper
C++WrapperforSketchUpCAPI
TypedValue.cpp
1 //
2 // TypedValue.cpp
3 //
4 // Sketchup C++ Wrapper for C API
5 // MIT License
6 //
7 // Copyright (c) 2017 Tom Kaneko
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
15 
16 // The above copyright notice and this permission notice shall be included in all
17 // copies or substantial portions of the Software.
18 
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 // SOFTWARE.
26 //
27 
28 // Macro for getting rid of unused variables commonly for assert checking
29 #define _unused(x) ((void)(x))
30 
31 #include <cassert>
32 #include <stdexcept>
33 
34 #include "SUAPI-CppWrapper/model/TypedValue.hpp"
35 #include "SUAPI-CppWrapper/Color.hpp"
36 #include "SUAPI-CppWrapper/Geometry.hpp"
37 #include "SUAPI-CppWrapper/String.hpp"
38 
39 namespace CW {
40 
41 TypedValue::TypedValue():
42  m_typed_value(create_typed_value()),
43  m_attached(false)
44 {}
45 
46 
47 TypedValue::TypedValue(SUTypedValueRef typed_val, bool attached):
48  m_typed_value(typed_val),
49  m_attached(attached)
50 {}
51 
52 
53 /** Copy constructor */
54 TypedValue::TypedValue(const TypedValue& other):
55  TypedValue()
56 {
57  // Redo copy assignment operator
58  (*this) = other;
59 }
60 
61 
63  switch (other.get_type()) {
64  case SUTypedValueType_Array:
65  {
66  std::vector<TypedValue> other_typed = other.typed_value_array();
67  typed_value_array(other_typed);
68  }
69  break;
70  case SUTypedValueType_Bool:
71  bool_value(other.bool_value());
72  break;
73  case SUTypedValueType_Byte:
74  byte_value(other.byte_value());
75  break;
76  case SUTypedValueType_Color:
77  color_value(other.color_value());
78  break;
79  case SUTypedValueType_Double:
80  double_value(other.double_value());
81  break;
82  case SUTypedValueType_Empty:
83  // Empty TypedValues are all the same.
84  break;
85  case SUTypedValueType_Float:
86  float_value(other.float_value());
87  break;
88  case SUTypedValueType_Int32:
89  int32_value(other.int32_value());
90  break;
91  case SUTypedValueType_Short:
92  // TODO
93  throw "this part hasn't been made yet.";
94  break;
95  case SUTypedValueType_String:
96  string_value(other.string_value());
97  break;
98  case SUTypedValueType_Time:
99  time_value(other.time_value());
100  break;
101  case SUTypedValueType_Vector3D:
102  vector_value(other.vector_value());
103  break;
104  }
105  return (*this);
106 }
107 
108 
109 SUTypedValueRef TypedValue::ref() const {
110  return m_typed_value;
111 }
112 
113 
114 TypedValue::operator SUTypedValueRef() {
115  return ref();
116 }
117 
118 
119 TypedValue::operator SUTypedValueRef*() {
120  return &m_typed_value;
121 }
122 
123 
124 bool TypedValue::operator!() const {
125  if (SUIsValid(m_typed_value)) {
126  return false;
127  }
128  return true;
129 }
130 
131 
132 bool TypedValue::empty() const {
133  if (SUIsInvalid(m_typed_value) ||
134  get_type() == SUTypedValueType::SUTypedValueType_Empty) {
135  return true;
136  }
137  return false;
138 }
139 
140 
141 /*
142 * Static member function
143 */
144 SUTypedValueRef TypedValue::create_typed_value() {
145  SUTypedValueRef typed_value = SU_INVALID;
146  SUResult res = SUTypedValueCreate(&typed_value);
147  assert(res == SU_ERROR_NONE); _unused(res);
148  return typed_value;
149 }
150 
151 
152 TypedValue::~TypedValue() {
153  if (SUIsValid(m_typed_value) && !m_attached) {
154  SUResult res = SUTypedValueRelease(&m_typed_value);
155  assert(res == SU_ERROR_NONE); _unused(res);
156  }
157 }
158 
159 
160 SUTypedValueType TypedValue::get_type() const {
161  if (!(*this)) {
162  throw std::logic_error("CW::TypedValue::get_type(): TypedValue is null");
163  }
164  SUTypedValueType type;
165  SUResult res = SUTypedValueGetType(m_typed_value, &type);
166  assert(res == SU_ERROR_NONE); _unused(res);
167  return type;
168 }
169 
170 
172  if (!(*this)) {
173  throw std::logic_error("CW::TypedValue::byte_value(): TypedValue is null");
174  }
175  if (get_type() != SUTypedValueType_Byte) {
176  throw std::logic_error("CW::TypedValue::byte_value(): TypedValue is not SUTypedValueType_Byte type");
177  }
178  char byte_val;
179  SUResult res = SUTypedValueGetByte(m_typed_value, &byte_val);
180  assert(res == SU_ERROR_NONE); _unused(res);
181  return byte_val;
182 }
183 
184 
185 TypedValue& TypedValue::byte_value(const char byte_val) {
186  if (!(*this)) {
187  m_typed_value = create_typed_value();
188  }
189  SUResult res = SUTypedValueSetByte(m_typed_value, byte_val);
190  assert(res == SU_ERROR_NONE); _unused(res);
191  return *this;
192 }
193 
194 
195 TypedValue::operator char() const {
196  return byte_value();
197 }
198 
199 
200 TypedValue::TypedValue(const char byte_val):
201  TypedValue()
202 {
203  this->byte_value(byte_val);
204 }
205 
206 
207 int16_t TypedValue::int16_value() const {
208  if (!(*this)) {
209  throw std::logic_error("CW::TypedValue::int16_value(): TypedValue is null");
210  }
211  if (get_type() != SUTypedValueType_Short) {
212  throw std::logic_error("CW::TypedValue::int16_value(): TypedValue is not SUTypedValueType_Short (Int16) type");
213  }
214  int16_t int16_val;
215  SUResult res = SUTypedValueGetInt16(m_typed_value, &int16_val);
216  assert(res == SU_ERROR_NONE); _unused(res);
217  return int16_val;
218 }
219 
220 
221 TypedValue& TypedValue::int16_value(const int16_t int16_val) {
222  if (!(*this)) {
223  m_typed_value = create_typed_value();
224  }
225  SUResult res = SUTypedValueSetInt16(m_typed_value, int16_val);
226  assert(res == SU_ERROR_NONE); _unused(res);
227  return *this;
228 }
229 
230 
231 TypedValue::operator int16_t() const {
232  return int16_value();
233 }
234 
235 
236 
237 TypedValue::TypedValue(const int16_t int16_val):
238  TypedValue()
239 {
240  this->int16_value(int16_val);
241 }
242 
243 
244 int32_t TypedValue::int32_value() const {
245  if (!(*this)) {
246  throw std::logic_error("CW::TypedValue::int32_value(): TypedValue is null");
247  }
248  if (get_type() != SUTypedValueType_Int32) {
249  throw std::logic_error("CW::TypedValue::int32_value(): TypedValue is not SUTypedValueType_Int32 type");
250  }
251  int32_t int32_val;
252  SUResult res = SUTypedValueGetInt32(m_typed_value, &int32_val);
253  assert(res == SU_ERROR_NONE); _unused(res);
254  return int32_val;
255 }
256 
257 
258 TypedValue& TypedValue::int32_value(const int32_t int32_val) {
259  if (!(*this)) {
260  m_typed_value = create_typed_value();
261  }
262  SUResult res = SUTypedValueSetInt32(m_typed_value, int32_val);
263  assert(res == SU_ERROR_NONE); _unused(res);
264  return *this;
265 }
266 
267 
268 TypedValue::operator int32_t() const {
269  return int32_value();
270 }
271 
272 
273 TypedValue::TypedValue(const int32_t int32_val):
274  TypedValue()
275 {
276  this->int32_value(int32_val);
277 }
278 
279 
281  if (!(*this)) {
282  throw std::logic_error("CW::TypedValue::float_value(): TypedValue is null");
283  }
284  if (get_type() != SUTypedValueType_Float) {
285  throw std::logic_error("CW::TypedValue::float_value(): TypedValue is not SUTypedValueType_Float type");
286  }
287  float float_val;
288  SUResult res = SUTypedValueGetFloat(m_typed_value, &float_val);
289  assert(res == SU_ERROR_NONE); _unused(res);
290  return float_val;
291 }
292 
293 
294 TypedValue& TypedValue::float_value(const float float_val) {
295  if (!(*this)) {
296  m_typed_value = create_typed_value();
297  }
298  SUResult res = SUTypedValueSetFloat(m_typed_value, float_val);
299  assert(res == SU_ERROR_NONE); _unused(res);
300  return *this;
301 }
302 
303 
304 TypedValue::operator float() const {
305  return float_value();
306 }
307 
308 
309 TypedValue::TypedValue(const float float_val):
310  TypedValue()
311 {
312  this->float_value(float_val);
313 }
314 
315 
316 double TypedValue::double_value() const {
317  if (!(*this)) {
318  throw std::logic_error("CW::TypedValue::double_value(): TypedValue is null");
319  }
320  if (get_type() != SUTypedValueType_Double) {
321  throw std::logic_error("CW::TypedValue::double_value(): TypedValue is not SUTypedValueType_Double type");
322  }
323  double double_val;
324  SUResult res = SUTypedValueGetDouble(m_typed_value, &double_val);
325  assert(res == SU_ERROR_NONE); _unused(res);
326  return double_val;
327 }
328 
329 
330 TypedValue& TypedValue::double_value(const double double_val) {
331  if (!(*this)) {
332  m_typed_value = create_typed_value();
333  }
334  SUResult res = SUTypedValueSetDouble(m_typed_value, double_val);
335  assert(res == SU_ERROR_NONE); _unused(res);
336  return *this;
337 }
338 
339 
340 TypedValue::operator double() const {
341  return double_value();
342 }
343 
344 
345 TypedValue::TypedValue(const double double_val):
346  TypedValue()
347 {
348  this->double_value(double_val);
349 }
350 
351 
353  if (!(*this)) {
354  throw std::logic_error("CW::TypedValue::bool_value(): TypedValue is null");
355  }
356  if (get_type() != SUTypedValueType_Bool) {
357  throw std::logic_error("CW::TypedValue::bool_value(): TypedValue is not SUTypedValueType_Bool type");
358  }
359  bool bool_val;
360  SUResult res = SUTypedValueGetBool(m_typed_value, &bool_val);
361  assert(res == SU_ERROR_NONE); _unused(res);
362  return bool_val;
363 }
364 
365 
366 TypedValue& TypedValue::bool_value(const bool bool_val) {
367  if (!(*this)) {
368  m_typed_value = create_typed_value();
369  }
370  SUResult res = SUTypedValueSetBool(m_typed_value, bool_val);
371  assert(res == SU_ERROR_NONE); _unused(res);
372  return *this;
373 }
374 
375 
376 TypedValue::operator bool() const {
377  return bool_value();
378 }
379 
380 
381 TypedValue::TypedValue(const bool bool_val):
382  TypedValue()
383 {
384  this->bool_value(bool_val);
385 }
386 
387 
389  if (!(*this)) {
390  throw std::logic_error("CW::TypedValue::color_value(): TypedValue is null");
391  }
392  if (get_type() != SUTypedValueType_Color) {
393  throw std::logic_error("CW::TypedValue::color_value(): TypedValue is not SUTypedValueType_Color type");
394  }
395  SUColor color_val;
396  SUResult res = SUTypedValueGetColor(m_typed_value, &color_val);
397  assert(res == SU_ERROR_NONE); _unused(res);
398  return Color(color_val);
399 }
400 
401 
402 TypedValue& TypedValue::color_value(const Color &color_val) {
403  if (!(*this)) {
404  m_typed_value = create_typed_value();
405  }
406  SUColor color = color_val.ref();
407  SUResult res = SUTypedValueSetColor(m_typed_value, &color);
408  assert(res == SU_ERROR_NONE); _unused(res);
409  return *this;
410 }
411 
412 
413 TypedValue::operator Color() const {
414  return color_value();
415 }
416 
417 
418 TypedValue::TypedValue(const Color &color_val):
419  TypedValue()
420 {
421  this->color_value(color_val);
422 }
423 
424 
425 int64_t TypedValue::time_value() const {
426  if (!(*this)) {
427  throw std::logic_error("CW::TypedValue::time_value(): TypedValue is null");
428  }
429  if (get_type() != SUTypedValueType_Time) {
430  throw std::logic_error("CW::TypedValue::time_value(): TypedValue is not SUTypedValueType_Time type");
431  }
432  int64_t time_val;
433  SUResult res = SUTypedValueGetTime(m_typed_value, &time_val);
434  assert(res == SU_ERROR_NONE); _unused(res);
435  return time_val;
436 }
437 
438 
439 TypedValue& TypedValue::time_value(const int64_t time_val) {
440  if (!(*this)) {
441  m_typed_value = create_typed_value();
442  }
443  SUResult res = SUTypedValueSetTime(m_typed_value, time_val);
444  assert(res == SU_ERROR_NONE); _unused(res);
445  return *this;
446 }
447 
448 
449 TypedValue::operator int64_t() const {
450  return time_value();
451 }
452 
453 
454 TypedValue::TypedValue(const int64_t time_val):
455  TypedValue()
456 {
457  this->time_value(time_val);
458 }
459 
460 
462  if (!(*this)) {
463  throw std::logic_error("CW::TypedValue::string_value(): TypedValue is null");
464  }
465  if (get_type() != SUTypedValueType_String) {
466  throw std::logic_error("CW::TypedValue::string_value(): TypedValue is not SUTypedValueType_String type");
467  }
468  String string;
469  SUStringRef &string_ref = string;
470  SUResult res = SUTypedValueGetString(m_typed_value, &string_ref);
471  assert(res == SU_ERROR_NONE); _unused(res);
472  return string;
473 }
474 
475 
476 TypedValue& TypedValue::string_value(const String &string_val) {
477  if (!(*this)) {
478  m_typed_value = create_typed_value();
479  }
480  std::string std_string = string_val;
481  SUResult res = SUTypedValueSetString(m_typed_value, std_string.c_str());
482  assert(res == SU_ERROR_NONE); _unused(res);
483  return *this;
484 }
485 
486 
487 TypedValue& TypedValue::string_value(const std::string &string_val) {
488  return string_value(String(string_val));
489 }
490 
491 
492 TypedValue::operator String() const {
493  return string_value();
494 }
495 
496 
497 TypedValue::operator std::string() const {
498  return string_value();
499 }
500 
501 
502 TypedValue::TypedValue(const char chars[]):
503  TypedValue(String(chars))
504 {}
505 
506 
507 TypedValue::TypedValue(const std::string& string):
508  TypedValue(string.data())
509 {}
510 
511 
512 TypedValue::TypedValue(const String& string):
513  TypedValue()
514 {
515  this->string_value(string);
516 }
517 
518 
519 
521  if (!(*this)) {
522  throw std::logic_error("CW::TypedValue::vector_value(): TypedValue is null");
523  }
524  if (get_type() != SUTypedValueType_Vector3D) {
525  throw std::logic_error("CW::TypedValue::vector_value(): TypedValue is not SUTypedValueType_Vector3D type");
526  }
527  double vector3d_value[3];
528  SUResult res = SUTypedValueGetVector3d(m_typed_value, &vector3d_value[0]);
529  assert(res == SU_ERROR_NONE); _unused(res);
530  return Vector3D(vector3d_value[0], vector3d_value[1], vector3d_value[2]);
531 }
532 
533 
534 TypedValue& TypedValue::vector_value(const Vector3D &vector_val) {
535  if (!(*this)) {
536  m_typed_value = create_typed_value();
537  }
538  double vector3d_value[3] = {vector_val.x, vector_val.y, vector_val.z};
539  SUResult res = SUTypedValueSetVector3d(m_typed_value, &vector3d_value[0]);
540  assert(res == SU_ERROR_NONE); _unused(res);
541  return *this;
542 }
543 
544 
545 TypedValue::operator Vector3D() const {
546  return vector_value();
547 }
548 
549 
550 TypedValue::TypedValue(const Vector3D& vector):
551  TypedValue()
552 {
553  this->vector_value(vector);
554 }
555 
556 
557 std::vector<TypedValue> TypedValue::typed_value_array() const {
558  if (!(*this)) {
559  throw std::logic_error("CW::TypedValue::typed_value_array(): TypedValue is null");
560  }
561  if (get_type() != SUTypedValueType_Array) {
562  throw std::logic_error("CW::TypedValue::typed_value_array(): TypedValue is not SUTypedValueType_Array type");
563  }
564  size_t count = 0;
565  SUResult res = SUTypedValueGetNumArrayItems(m_typed_value, &count);
566  assert(res == SU_ERROR_NONE);
567  std::vector<SUTypedValueRef> value_refs(count, SU_INVALID);
568  res = SUTypedValueGetArrayItems(m_typed_value, count, value_refs.data(), &count);
569  assert(res == SU_ERROR_NONE); _unused(res);
570  // TypedValue from TypedValue arrays should not actually be released. This poses a problem for the wrapper object which will want to release it. The solution is to copy these special TypedValues that don't release into new TypedValue objects that do.
571  std::vector<TypedValue> temp_vals(count);
572  std::transform(value_refs.begin(), value_refs.end(), temp_vals.begin(),
573  [](const SUTypedValueRef& value) {
574  return TypedValue(value, true);
575  });
576  std::vector<TypedValue> typed_vals(count);
577  // Force a copy operation to create an object that will be released normally.
578  for (size_t i=0; i < typed_vals.size(); i++) {
579  typed_vals[i] = temp_vals[i];
580  }
581  return typed_vals;
582 }
583 
584 
585 TypedValue& TypedValue::typed_value_array(std::vector<TypedValue> &typed_val_array) {
586  if (!(*this)) {
587  m_typed_value = create_typed_value();
588  }
589  SUResult res = SU_ERROR_NONE;
590  std::vector<SUTypedValueRef> refs{typed_val_array.size(), SU_INVALID };
591  std::transform(typed_val_array.begin(), typed_val_array.end(), refs.begin(),
592  [](const CW::TypedValue& typed_value) {return typed_value.ref(); });
593  res = SUTypedValueSetArrayItems(m_typed_value, refs.size(), refs.data());
594  assert(res == SU_ERROR_NONE); _unused(res);
595  return *this;
596 }
597 
598 
599 TypedValue::operator std::vector<TypedValue>() const {
600  return typed_value_array();
601 }
602 
603 
604 TypedValue::TypedValue(std::vector<TypedValue> &typed_val_array):
605  TypedValue()
606 {
607  this->typed_value_array(typed_val_array);
608 }
609 
610 
611 bool operator== (const TypedValue &val1, const TypedValue &val2) {
612  // Check validity
613  if (SUIsInvalid(val1.m_typed_value) || SUIsInvalid(val1.m_typed_value)) {
614  if (SUIsInvalid(val1.m_typed_value) && SUIsInvalid(val1.m_typed_value)) {
615  return true;
616  }
617  return false;
618  }
619  // Check types
620  if (val1.get_type() != val1.get_type()) {
621  return false;
622  }
623  switch (val1.get_type()) {
624  case SUTypedValueType_Array:
625  if (val1.typed_value_array() == val2.typed_value_array()) {
626  return true;
627  }
628  return false;
629  break;
630  case SUTypedValueType_Bool:
631  if (val1.bool_value() == val2.bool_value()) {
632  return true;
633  }
634  return false;
635  break;
636  case SUTypedValueType_Byte:
637  if (val1.byte_value() == val2.byte_value()) {
638  return true;
639  }
640  return false;
641  break;
642  case SUTypedValueType_Color:
643  if (val1.color_value() == val2.color_value()) {
644  return true;
645  }
646  return false;
647  break;
648  case SUTypedValueType_Double:
649  if (val1.double_value() == val2.double_value()) {
650  return true;
651  }
652  return false;
653  break;
654  case SUTypedValueType_Empty:
655  // Empty TypedValues are all the same.
656  return true;
657  break;
658  case SUTypedValueType_Float:
659  if (val1.float_value() == val2.float_value()) {
660  return true;
661  }
662  return false;
663  break;
664  case SUTypedValueType_Int32:
665  if (val1.int32_value() == val2.int32_value()) {
666  return true;
667  }
668  return false;
669  break;
670  case SUTypedValueType_Short:
671  // TODO
672  throw "this part hasn't been made yet.";
673  break;
674  case SUTypedValueType_String:
675  if (val1.string_value() == val2.string_value()) {
676  return true;
677  }
678  return false;
679 
680  break;
681  case SUTypedValueType_Time:
682  if (val1.time_value() == val2.time_value()) {
683  return true;
684  }
685  return false;
686  break;
687  case SUTypedValueType_Vector3D:
688  if (val1.vector_value() == val2.vector_value()) {
689  return true;
690  }
691  return false;
692  break;
693  }
694  return false;
695 }
696 
697 bool operator!= (const TypedValue &val1, const TypedValue &val2) {
698  if (val1 == val2) {
699  return false;
700  }
701  return true;
702 }
703 
704 
705 } /* namespace CW */
TypedValue & operator=(const TypedValue &other)
Definition: TypedValue.cpp:62
double double_value() const
Definition: TypedValue.cpp:316
bool m_attached
Indicates whether the Entity has been attached to a model.
Definition: Entity.hpp:64
float float_value() const
Definition: TypedValue.cpp:280
int64_t time_value() const
Definition: TypedValue.cpp:425
bool attached() const
Returns true if the entity is attached to another object.
Definition: Entity.cpp:100
std::vector< TypedValue > typed_value_array() const
Definition: TypedValue.cpp:557
Color color_value() const
Definition: TypedValue.cpp:388
char byte_value() const
Definition: TypedValue.cpp:171
bool operator!() const
Definition: TypedValue.cpp:124
int32_t int32_value() const
Definition: TypedValue.cpp:244
friend bool operator==(const TypedValue &val1, const TypedValue &val2)
Definition: TypedValue.cpp:611
SUTypedValueType get_type() const
Definition: TypedValue.cpp:160
Vector3D vector_value() const
Definition: TypedValue.cpp:520
String string_value() const
Definition: TypedValue.cpp:461
Definition: Color.hpp:34
bool bool_value() const
Definition: TypedValue.cpp:352
bool empty() const
Definition: TypedValue.cpp:132
int16_t int16_value() const
Definition: TypedValue.cpp:207