MADARA  3.4.1
CompositeArrayReference.cpp
Go to the documentation of this file.
1 
2 #ifndef _MADARA_NO_KARL_
3 
7 #include "VariableExpander.h"
8 
9 #include <string>
10 #include <sstream>
11 
13  const std::string& key, ComponentNode* index,
15  : CompositeUnaryNode(context.get_logger(), index),
16  context_(context),
17  key_(key),
18  key_expansion_necessary_(false)
19 {
20  VariableExpander expander;
21  ref_ = expander.expand(key, "CompositeArrayReference", context, logger_,
23 }
24 
26 {
27  if (key_expansion_necessary_)
28  {
30  "Variable %s requires variable expansion\n", key_.c_str());
31 
32  unsigned int count = 0;
33 
34  // add the first token into a string builder
35  std::stringstream builder;
36  std::vector<std::string>::const_iterator token = tokens_.begin();
37  builder << *token;
38 
39  // move the token to the next in the list.
40  for (++token, ++count; token != tokens_.end(); ++token, ++count)
41  {
42  if (*token != "")
43  {
44  // is the current token a variable to lookup?
45  if (count < pivot_list_.size() && pivot_list_[count] == "}")
46  {
47  builder << context_.get_record(*token)->to_string();
48  }
49  else
50  {
51  builder << *token;
52  }
53  }
54  }
55 
56  return builder.str();
57  }
58  // if there was no need to expand the key, just return
59  // the key
60  else
61  return key_;
62 }
63 
65 {
66  visitor.visit(*this);
67 }
68 
71 {
72  size_t index = right_->item().to_integer();
73 
74  if (ref_.is_valid())
75  {
76  return ref_.get_record_unsafe()->retrieve_index(index);
77  }
78  else
79  {
80  return context_.get(expand_key()).retrieve_index(index);
81  }
82 }
83 
89 {
90  // a variable is one of very few nodes that can change over time and
91  // cannot be pruned
92  can_change = true;
93 
94  std::string key = expand_key();
95 
96  if (key == "nan")
97  {
99  "CompositeArrayReference::prune: "
100  "KARL COMPILE ERROR:"
101  "Reserved word 'nan' used as an array reference.\n",
102  key_.c_str());
103 
104  // return new LeafNode (context_.get_logger (), NAN);
106  "madara::expression::ComponentNode: "
107  "KARL COMPILE ERROR: "
108  "Reserved word 'nan' used as an array reference.");
109  }
110  else if (key == "inf")
111  {
113  "CompositeArrayReference::prune: "
114  "KARL COMPILE ERROR:"
115  "Reserved word 'inf' used as an array reference.\n",
116  key_.c_str());
117 
118  // return new LeafNode (context_.get_logger (), NAN);
120  "madara::expression::ComponentNode: "
121  "KARL COMPILE ERROR: "
122  "Reserved word 'inf' used as an array reference.");
123  }
124 
125  // we could call item(), but since it is virtual, it incurs unnecessary
126  // overhead.
127  if (ref_.is_valid())
128  return *ref_.get_record_unsafe();
129  else
130  return context_.get(expand_key());
131 }
132 
138 {
139  size_t index = right_->evaluate(settings).to_integer();
140 
141  if (ref_.is_valid())
142  {
143  auto ret = ref_.get_record_unsafe();
144 
145  if (settings.exception_on_unitialized && !ret->exists ())
146  {
147  std::stringstream buffer;
148  buffer << "madara::expression::CompositeArrayReference::evaluate: ";
149  buffer << "ERROR: settings do not allow reads of unset vars and ";
150  buffer << ref_.get_name() << " is uninitialized";
151  throw exceptions::UninitializedException (buffer.str ());
152  }
153 
154  return ret->retrieve_index(index);
155  }
156  else
157  {
158  auto ret = context_.get(expand_key()).retrieve_index(index);
159 
160  if (settings.exception_on_unitialized && !ret.exists ())
161  {
162  std::stringstream buffer;
163  buffer << "madara::expression::CompositeArrayReference::evaluate: ";
164  buffer << "ERROR: settings do not allow reads of unset vars and ";
165  buffer << ref_.get_name() << " is uninitialized";
166  throw exceptions::UninitializedException (buffer.str ());
167  }
168 
169  return ret;
170  }
171 }
172 
174 {
175  return key_;
176 }
177 
182 {
183  size_t index = size_t(right_->evaluate(settings).to_integer());
184 
185  if (ref_.is_valid())
186  {
187  auto record = ref_.get_record_unsafe();
188 
189  // notice that we assume the context is locked
190  // check if we have the appropriate write quality
191  if (!settings.always_overwrite && record->write_quality < record->quality)
192  return context_.retrieve_index(expand_key(), index, settings);
193 
194  // cheaper to read than write, so check to see if
195  // we actually need to update quality and status
196  if (record->write_quality != record->quality)
197  record->quality = record->write_quality;
198 
199  knowledge::KnowledgeRecord result(record->dec_index(index));
200 
201  context_.mark_and_signal(ref_);
202 
203  return result;
204  }
205  else
206  {
208  context_.retrieve_index(expand_key(), index, settings) -
210 
212  context_.set_index(expand_key(), index, result.to_integer(), settings);
213  else if (result.type() == knowledge::KnowledgeRecord::DOUBLE)
214  context_.set_index(expand_key(), index, result.to_double(), settings);
215 
216  return result;
217  }
218 }
219 
224 {
225  size_t index = size_t(right_->evaluate(settings).to_integer());
226 
227  if (ref_.is_valid())
228  {
229  auto record = ref_.get_record_unsafe();
230 
231  // notice that we assume the context is locked
232  // check if we have the appropriate write quality
233  if (!settings.always_overwrite && record->write_quality < record->quality)
234  return context_.retrieve_index(expand_key(), index, settings);
235 
236  // cheaper to read than write, so check to see if
237  // we actually need to update quality and status
238  if (record->write_quality != record->quality)
239  record->quality = record->write_quality;
240 
241  knowledge::KnowledgeRecord result(record->inc_index(index));
242 
243  context_.mark_and_signal(ref_);
244 
245  return result;
246  }
247  else
248  {
250  context_.retrieve_index(expand_key(), index, settings) +
252 
254  context_.set_index(expand_key(), index, result.to_integer(), settings);
255  else if (result.type() == knowledge::KnowledgeRecord::DOUBLE)
256  context_.set_index(expand_key(), index, result.to_double(), settings);
257 
258  return result;
259  }
260 }
261 
265 {
266  int return_value = 0;
267 
269  return_value = set(value.to_integer(), settings);
270  else if (value.type() == knowledge::KnowledgeRecord::DOUBLE)
271  return_value = set(value.to_double(), settings);
272 
273  return return_value;
274 }
275 
279 {
280  size_t index = size_t(right_->evaluate(settings).to_integer());
281 
282  if (ref_.is_valid())
283  {
284  auto record = ref_.get_record_unsafe();
285 
286  // notice that we assume the context is locked
287  // check if we have the appropriate write quality
288  if (!settings.always_overwrite && record->write_quality < record->quality)
289  return -2;
290 
291  // cheaper to read than write, so check to see if
292  // we actually need to update quality and status
293  if (record->write_quality != record->quality)
294  record->quality = record->write_quality;
295 
296  record->set_index(index, value);
297 
298  context_.mark_and_signal(ref_);
299 
300  return 0;
301  }
302  else
303  return context_.set_index(expand_key(), index, value, settings);
304 }
305 
307  double value, const madara::knowledge::KnowledgeUpdateSettings& settings)
308 {
309  size_t index = size_t(right_->evaluate(settings).to_integer());
310 
311  if (ref_.is_valid())
312  {
313  auto record = ref_.get_record_unsafe();
314 
315  // notice that we assume the context is locked
316  // check if we have the appropriate write quality
317  if (!settings.always_overwrite && record->write_quality < record->quality)
318  return -2;
319 
320  // cheaper to read than write, so check to see if
321  // we actually need to update quality and status
322  if (record->write_quality != record->quality)
323  record->quality = record->write_quality;
324 
325  record->set_index(index, value);
326 
327  context_.mark_and_signal(ref_);
328 
329  return 0;
330  }
331  else
332  return context_.set_index(expand_key(), index, value, settings);
333 }
334 
335 #endif // _MADARA_NO_KARL_
#define madara_logger_ptr_log(loggering, level,...)
Fast version of the madara::logger::log method for Logger pointers.
Definition: Logger.h:41
const ThreadSafeContext * context_
madara::knowledge::KnowledgeRecord KnowledgeRecord
An exception for unrecoverable KaRL compilation issues.
Definition: KarlException.h:21
An exception for attempting to access an invalid context1.
An abstract base class defines a simple abstract implementation of an expression tree node.
Definition: ComponentNode.h:37
logger::Logger * logger_
handle the context
Definition: ComponentNode.h:96
std::string expand_key(void) const
Expands the key (if necessary).
const std::string & key(void) const
Return the variable key.
virtual madara::knowledge::KnowledgeRecord evaluate(const madara::knowledge::KnowledgeUpdateSettings &settings)
Evaluates the node and its children.
CompositeArrayReference(const std::string &key, ComponentNode *index, madara::knowledge::ThreadSafeContext &context)
Constructor.
virtual madara::knowledge::KnowledgeRecord prune(bool &can_change)
Prune the tree of unnecessary nodes.
knowledge::KnowledgeRecord inc(const madara::knowledge::KnowledgeUpdateSettings &settings=knowledge::KnowledgeUpdateSettings())
Sets the value stored in the node.
virtual void accept(Visitor &visitor) const
Define the accept() operation used for the Visitor pattern.
int set(const madara::knowledge::KnowledgeRecord::Integer &value, const madara::knowledge::KnowledgeUpdateSettings &settings=knowledge::KnowledgeUpdateSettings())
Sets the value stored in the node.
virtual madara::knowledge::KnowledgeRecord item(void) const
Return the item stored in the node.
madara::knowledge::VariableReference ref_
knowledge::KnowledgeRecord dec(const madara::knowledge::KnowledgeUpdateSettings &settings=knowledge::KnowledgeUpdateSettings())
Sets the value stored in the node.
Encapsulates a single expression tree.
madara::knowledge::VariableReference expand(const std::string &key, const std::string &print_prefix, madara::knowledge::ThreadSafeContext &context, madara::logger::Logger *cur_logger, bool &key_expansion_necessary, std::vector< std::string > &splitters, std::vector< std::string > &tokens, std::vector< std::string > &pivot_list)
Expands a key into either a VariableReference or tokens.
Abstract base class for all visitors to all classes that derive from ComponentNode.
Definition: Visitor.h:93
virtual void visit(const LeafNode &node)=0
Visit a LeafNode.
This class encapsulates an entry in a KnowledgeBase.
uint32_t type(void) const
returns the type of the value
double to_double(void) const
converts the value to a float/double.
Integer to_integer(void) const
converts the value to an integer.
bool exception_on_unitialized
throw an exception if reference is on uninitialized variable
Settings for applying knowledge updates.
bool always_overwrite
Toggle for always overwriting records, regardless of quality, clock values, etc.
This class stores variables and their values for use by any entity needing state information in a thr...
constexpr string_t string