MADARA  3.1.8
CompositeArrayReference.cpp
Go to the documentation of this file.
1 
2 #ifndef _MADARA_NO_KARL_
3 
7 
8 
9 #include <string>
10 #include <sstream>
11 
13  const std::string & key, ComponentNode * index,
15 : CompositeUnaryNode (context.get_logger (), index),
16  key_ (key), record_ (0),
17  context_ (context), key_expansion_necessary_ (false)
18 {
19  // this key requires expansion. We do the compilation and error checking here
20  // as the key shouldn't change, and this allows us to only have to do this
21  // once
22  if (key.find ("{") != key.npos)
23  {
25  "Variable %s requires variable expansion.\n",
26  key.c_str ());
27 
29  splitters_.push_back ("{");
30  splitters_.push_back ("}");
31 
33 
34  if (pivot_list_.size () % 2 != 0)
35  {
37  "KARL COMPILE ERROR: matching braces not found in %s\n",
38  key.c_str ());
39 
40  exit (-1);
41  }
42 
43  // check for braces that are not properly closed
44  std::vector<std::string>::const_iterator pivot = pivot_list_.begin ();
45  unsigned int num_opens = 0;
46  unsigned int num_closes = 0;
47 
48  for (; pivot != pivot_list_.end (); ++pivot)
49  {
50  if (*pivot == "{")
51  {
52  ++num_opens;
53  }
54  else if (*pivot == "}")
55  {
56  ++num_closes;
57  }
58  }
59 
60  if (num_opens > num_closes)
61  {
63  "KARL COMPILE ERROR: Array name has "
64  "more opening braces than closing in %s\n",
65  key.c_str ());
66 
67  exit (-1);
68  }
69  else if (num_closes > num_opens)
70  {
72  "KARL COMPILE ERROR: Array name has "
73  "more closing braces than opening in %s\n",
74  key.c_str ());
75 
76  exit (-1);
77  }
78  }
79  // no variable expansion necessary. Create a hard link to the record_->
80  // this will save us lots of clock cycles each variable access or
81  // mutation.
82  else
83  {
84  record_ = context_.get_record (key);
85  }
86 }
87 
89 {
90  // do not clean up record_. Let the context clean that up.
91 }
92 
95 {
97  {
99  "Variable %s requires variable expansion\n",
100  key_.c_str ());
101 
102  unsigned int count = 0;
103 
104  // add the first token into a string builder
105  std::stringstream builder;
106  std::vector< std::string>::const_iterator token = tokens_.begin ();
107  builder << *token;
108 
109  // move the token to the next in the list.
110  for (++token, ++count; token != tokens_.end (); ++token, ++count)
111  {
112  if (*token != "")
113  {
114  // is the current token a variable to lookup?
115  if (count < pivot_list_.size ()
116  && pivot_list_[count] == "}")
117  {
118  builder << context_.get_record (*token)->to_string ();
119  }
120  else
121  {
122  builder << *token;
123  }
124  }
125  }
126 
127  return builder.str ();
128  }
129  // if there was no need to expand the key, just return
130  // the key
131  else
132  return key_;
133 }
134 
135 
136 void
138 {
139  visitor.visit (*this);
140 }
141 
144 {
145  size_t index = right_->item ().to_integer ();
146 
147  if (record_)
148  {
149  return record_->retrieve_index (index);
150  }
151  else
152  return context_.get (expand_key ()).retrieve_index (index);
153 }
154 
160 {
161  // a variable is one of very few nodes that can change over time and
162  // cannot be pruned
163  can_change = true;
164 
165  // we could call item(), but since it is virtual, it incurs unnecessary
166  // overhead.
167  if (record_)
168  return *record_;
169  else
170  return context_.get (expand_key ());
171 }
172 
178 {
179  size_t index = right_->evaluate (settings).to_integer ();
180 
181  if (record_)
182  {
183  return record_->retrieve_index (index);
184  }
185  else
186  return context_.get (expand_key ()).retrieve_index (index);
187 }
188 
189 const std::string &
191 {
192  return key_;
193 }
194 
195 
200 {
201  size_t index = size_t (right_->evaluate (settings).to_integer ());
202 
203  if (record_)
204  {
205  // notice that we assume the context is locked
206  // check if we have the appropriate write quality
208  return context_.retrieve_index (expand_key (), index, settings);
209 
210  // cheaper to read than write, so check to see if
211  // we actually need to update quality and status
214 
215  knowledge::KnowledgeRecord result (record_->dec_index (index));
216 
218 
219  return result;
220  }
221  else
222  {
224  context_.retrieve_index (expand_key (), index, settings) - knowledge::KnowledgeRecord (1));
225 
226  if (result.type () == knowledge::KnowledgeRecord::INTEGER)
227  context_.set_index (expand_key (), index, result.to_integer (), settings);
228  else if (result.type () == knowledge::KnowledgeRecord::DOUBLE)
229  context_.set_index (expand_key (), index, result.to_double (), settings);
230 
231  return result;
232  }
233 }
234 
239 {
240  size_t index = size_t (right_->evaluate (settings).to_integer ());
241 
242  if (record_)
243  {
244  // notice that we assume the context is locked
245  // check if we have the appropriate write quality
247  return context_.retrieve_index (expand_key (), index, settings);
248 
249  // cheaper to read than write, so check to see if
250  // we actually need to update quality and status
253 
254  knowledge::KnowledgeRecord result (record_->inc_index (index));
255 
257 
258  return result;
259  }
260  else
261  {
263  context_.retrieve_index (expand_key (), index, settings)
265 
266  if (result.type () == knowledge::KnowledgeRecord::INTEGER)
267  context_.set_index (expand_key (), index, result.to_integer (), settings);
268  else if (result.type () == knowledge::KnowledgeRecord::DOUBLE)
269  context_.set_index (expand_key (), index, result.to_double (), settings);
270 
271  return result;
272  }
273 }
274 
275 int
279 {
280  int return_value = 0;
281 
283  return_value = set (value.to_integer (), settings);
284  else if (value.type () == knowledge::KnowledgeRecord::DOUBLE)
285  return_value = set (value.to_double (), settings);
286 
287  return return_value;
288 }
289 
290 int
293 {
294  size_t index = size_t (right_->evaluate (settings).to_integer ());
295 
296  if (record_)
297  {
298  // notice that we assume the context is locked
299  // check if we have the appropriate write quality
301  return -2;
302 
303  // cheaper to read than write, so check to see if
304  // we actually need to update quality and status
307 
308  record_->set_index (index, value);
309 
311 
312  return 0;
313  }
314  else
315  return context_.set_index (expand_key (), index, value, settings);
316 }
317 
318 int
321 {
322  size_t index = size_t (right_->evaluate (settings).to_integer ());
323 
324  if (record_)
325  {
326  // notice that we assume the context is locked
327  // check if we have the appropriate write quality
329  return -2;
330 
331  // cheaper to read than write, so check to see if
332  // we actually need to update quality and status
335 
336  record_->set_index (index, value);
337 
339 
340  return 0;
341  }
342  else
343  return context_.set_index (expand_key (), index, value, settings);
344 }
345 
346 #endif // _MADARA_NO_KARL_
This class encapsulates an entry in a KnowledgeBase.
virtual madara::knowledge::KnowledgeRecord prune(bool &can_change)
Prune the tree of unnecessary nodes.
const std::string key_
Key for retrieving value of this variable.
KnowledgeRecord retrieve_index(const std::string &key, size_t index, const KnowledgeReferenceSettings &settings=KnowledgeReferenceSettings())
Retrieves a value at a specified index within a knowledge array.
int32_t type(void) const
returns the size of the value
int set(const madara::knowledge::KnowledgeRecord::Integer &value, const madara::knowledge::KnowledgeUpdateSettings &settings=knowledge::KnowledgeUpdateSettings())
Sets the value stored in the node.
ComponentNode * right_
Right expression.
madara::knowledge::KnowledgeRecord get(const std::string &key, const KnowledgeReferenceSettings &settings=KnowledgeReferenceSettings()) const
Atomically returns the value of a variable.
uint32_t quality
priority of the update
madara::knowledge::KnowledgeRecord KnowledgeRecord
double to_double(void) const
converts the value to a float/double
KnowledgeRecord inc_index(size_t index)
increments the value at the index to the specified value.
knowledge::KnowledgeRecord inc(const madara::knowledge::KnowledgeUpdateSettings &settings=knowledge::KnowledgeUpdateSettings())
Sets the value stored in the node.
virtual madara::knowledge::KnowledgeRecord item(void) const
Returns the value of the node.
logger::Logger * logger_
handle the context
Definition: ComponentNode.h:96
const std::string & key(void) const
Return the variable key.
This class stores variables and their values for use by any entity needing state information in a thr...
virtual madara::knowledge::KnowledgeRecord evaluate(const madara::knowledge::KnowledgeUpdateSettings &settings)=0
Evaluates the expression tree.
int set_index(const std::string &key, size_t index, T &&value, const KnowledgeUpdateSettings &settings=KnowledgeUpdateSettings())
Atomically sets the value of an array index to a value.
virtual void accept(Visitor &visitor) const
Define the accept() operation used for the Visitor pattern.
virtual madara::knowledge::KnowledgeRecord item(void) const
Return the item stored in the node.
madara::knowledge::KnowledgeRecord * record_
#define madara_logger_ptr_log(logger, level,...)
Fast version of the madara::logger::log method for Logger pointers.
Definition: Logger.h:32
An abstract base class defines a simple abstract implementation of an expression tree node...
Definition: ComponentNode.h:35
Abstract base class for all visitors to all classes that derive from ComponentNode.
Definition: Visitor.h:90
void set_index(size_t index, T value)
sets the value at the index to the specified value.
Integer to_integer(void) const
converts the value to an integer
static constexpr struct madara::knowledge::tags::string_t string
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.
knowledge::KnowledgeRecord dec(const madara::knowledge::KnowledgeUpdateSettings &settings=knowledge::KnowledgeUpdateSettings())
Sets the value stored in the node.
bool always_overwrite
Toggle for always overwriting records, regardless of quality, clock values, etc.
KnowledgeRecord * get_record(const std::string &key, const KnowledgeReferenceSettings &settings=KnowledgeReferenceSettings())
Retrieves a knowledge record from the key.
uint32_t write_quality
write priority for any local updates
madara::knowledge::ThreadSafeContext & context_
KnowledgeRecord dec_index(size_t index)
decrements the value at the index to the specified value.
Settings for applying knowledge updates.
Encapsulates a single expression tree.
virtual void visit(const LeafNode &node)=0
Visit a LeafNode.
KnowledgeRecord retrieve_index(size_t index) const
retrieves the value at an array index.
MADARA_Export void tokenizer(const std::string &input, const ::std::vector< std::string > &splitters,::std::vector< std::string > &tokens,::std::vector< std::string > &pivot_list)
Splits an input string into tokens.
Definition: Utility.cpp:291
std::string to_string(const std::string &delimiter=", ") const
converts the value to a string.
void mark_and_signal(const char *name, knowledge::KnowledgeRecord *record, const KnowledgeUpdateSettings &settings=KnowledgeUpdateSettings())
method for marking a record modified and signaling changes
std::string expand_key(void) const
Expands the key (if necessary).