SUAPI-CppWrapper
C++WrapperforSketchUpCAPI
AttributeDictionary.cpp
1 //
2 // AttributeDictionary.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 #include <algorithm>
34 
35 #include "SUAPI-CppWrapper/model/AttributeDictionary.hpp"
36 
37 #include "SUAPI-CppWrapper/model/TypedValue.hpp"
38 #include "SUAPI-CppWrapper/String.hpp"
39 
40 namespace CW {
41 
42 extern size_t SU_VERSION_MAJOR;
43 
44 /******************
45 * Private Static methods
46 *******************/
47 SUAttributeDictionaryRef AttributeDictionary::create_attribute_dictionary(const std::string& name) {
48  if (SU_VERSION_MAJOR < 18) {
49  throw std::logic_error("AttributeDictionary::create_attribute_dictionary(): Cannot use function prior to SU version 2018");
50  }
51  SUAttributeDictionaryRef dict = SU_INVALID;
52  SUResult res = SUAttributeDictionaryCreate(&dict, name.c_str());
53  assert(res == SU_ERROR_NONE);
54  _unused(res);
55  return dict;
56 }
57 
58 
59 SUAttributeDictionaryRef AttributeDictionary::copy_reference(const AttributeDictionary& other) {
60  if (SU_VERSION_MAJOR < 18) {
61  throw std::logic_error("AttributeDictionary::create_attribute_dictionary(): Cannot use function prior to SU version 2018");
62  }
63  if (other.m_attached || !other) {
64  return other.ref();
65  }
66  // The other Attributedictionary has not been attached to the model, so copy its properties to a new object
67  SUAttributeDictionaryRef new_dict = create_attribute_dictionary(other.get_name());
68  return new_dict;
69 }
70 
71 
72 /*****************************
73 * Constructor / Destructors **
74 ******************************/
76  Entity(SU_INVALID)
77 {}
78 
79 
81  AttributeDictionary(create_attribute_dictionary(name), false)
82 {}
83 
84 
85 AttributeDictionary::AttributeDictionary(SUAttributeDictionaryRef dict_ref, bool attached):
86  Entity(SUAttributeDictionaryToEntity(dict_ref), attached)
87 {}
88 
89 
90 /** Copy constructor */
92  Entity(other, SUAttributeDictionaryToEntity(copy_reference(other)))
93 {
94  if (!other.m_attached && SUIsValid(other.m_entity)) {
95  // Create a copy of the keys and values
96  std::vector<std::string> keys = other.get_keys();
97  for (size_t i=0; i < keys.size(); i++) {
98  this->set_attribute(keys[i], other.get_value(keys[i]));
99  }
100  }
101 }
102 
103 
105  if (SU_VERSION_MAJOR >= 18) {
106  if (!m_attached && SUIsValid(m_entity)) {
107  SUAttributeDictionaryRef dict = this->ref();
108  SUResult res = SUAttributeDictionaryRelease(&dict);
109  assert(res == SU_ERROR_NONE);
110  _unused(res);
111  }
112  }
113 }
114 
115 /******************
116 * Public Methods **
117 *******************/
118 /** Copy assignment operator */
120  if (SU_VERSION_MAJOR >= 18 && !m_attached && SUIsValid(m_entity)) {
121  SUAttributeDictionaryRef dict = this->ref();
122  SUResult res = SUAttributeDictionaryRelease(&dict);
123  assert(res == SU_ERROR_NONE);
124  _unused(res);
125  }
126  SUAttributeDictionaryRef dict = copy_reference(other);
127  m_entity = SUAttributeDictionaryToEntity(dict);
128  Entity::operator=(other);
129  return *this;
130 }
131 
132 
133 SUAttributeDictionaryRef AttributeDictionary::ref() const {
134  return SUAttributeDictionaryFromEntity(m_entity);
135 }
136 
137 
138 AttributeDictionary::operator SUAttributeDictionaryRef() const {
139  return this->ref();
140 }
141 
142 
143 TypedValue AttributeDictionary::get_attribute(const std::string &key, const TypedValue &default_value) const {
144  if (!(*this)) {
145  throw std::logic_error("CW::AttributeDictionary::get_attribute(): AttributeDictionary is null");
146  }
147  SUTypedValueRef val = SU_INVALID;
148  SUResult res = SUTypedValueCreate(&val);
149  assert(res == SU_ERROR_NONE);
150  const char* key_char = key.c_str();
151  res = SUAttributeDictionaryGetValue(this->ref(), &key_char[0], &val);
152  if (res == SU_ERROR_NO_DATA) {
153  return default_value;
154  }
155  assert(res == SU_ERROR_NONE); _unused(res);
156  return TypedValue(val);
157 }
158 
159 bool AttributeDictionary::set_attribute(const std::string &key, const TypedValue &value) {
160  if (!(*this)) {
161  throw std::logic_error("CW::AttributeDictionary::set_attribute(): AttributeDictionary is null");
162  }
163  SUResult res = SUAttributeDictionarySetValue(this->ref(), key.data(), value.ref());
164  if (res == SU_ERROR_NONE) {
165  return true;
166  }
167  else {
168  return false;
169  }
170 }
171 
172 std::vector<std::string> AttributeDictionary::get_keys() const {
173  if (!(*this)) {
174  throw std::logic_error("CW::AttributeDictionary::get_keys(): AttributeDictionary is null");
175  }
176  size_t num_keys = 0;
177  SUResult res = SUAttributeDictionaryGetNumKeys(this->ref(), &num_keys);
178  assert(res == SU_ERROR_NONE);
179  std::vector<SUStringRef> keys_ref(num_keys, SU_INVALID);
180  std::for_each(keys_ref.begin(), keys_ref.end(),
181  [](SUStringRef& value) {
182  SUResult res = SUStringCreate(&value);
183  assert(res == SU_ERROR_NONE); _unused(res);
184  });
185  res = SUAttributeDictionaryGetKeys(this->ref(), num_keys, keys_ref.data(), &num_keys);
186  assert(res == SU_ERROR_NONE); _unused(res);
187  std::vector<std::string> keys(num_keys);
188  std::transform(keys_ref.begin(), keys_ref.end(), keys.begin(),
189  [](const SUStringRef& value) {
190  return String(value).std_string();
191  });
192  return keys;
193 }
194 
195 TypedValue AttributeDictionary::get_value(const std::string &key) const {
196  return get_attribute(key, TypedValue());
197 }
198 
199 std::string AttributeDictionary::get_name() const {
200  String string;
201  SUStringRef *string_ref = string;
202  SUResult res = SUAttributeDictionaryGetName(this->ref(), string_ref);
203  assert(res == SU_ERROR_NONE);
204  _unused(res);
205  return string;
206 }
207 
209  if (SUIsValid(m_entity)) {
210  return false;
211  }
212  return true;
213 }
214 
215 
216 } /* namespace CW */
bool m_attached
Indicates whether the Entity has been attached to a model.
Definition: Entity.hpp:64
SUAttributeDictionaryRef ref() const
std::string get_name() const
AttributeDictionary & operator=(const AttributeDictionary &other)
bool attached() const
Returns true if the entity is attached to another object.
Definition: Entity.cpp:100
TypedValue get_attribute(const std::string &key, const TypedValue &default_value) const
TypedValue get_value(const std::string &key) const
SUEntityRef m_entity
The C SUEntityRef that this class wraps.
Definition: Entity.hpp:59
Definition: Color.hpp:34
std::vector< std::string > get_keys() const
bool set_attribute(const std::string &key, const TypedValue &value)
Entity & operator=(const Entity &other)
Copy assignment operator.
Definition: Entity.cpp:73