Calculator
Extensible stack-based calculator primarily in library form
Stack.h
Go to the documentation of this file.
1 /*
2 Copyright (c) 2013, Komodo Does Inc
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6 
7 - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 - Neither the name of the Komodo Does Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10 
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 */
13 
14 #ifndef STACK_H
15 #define STACK_H
16 
17 #ifndef RESULT_H
18 #include "Result.h"
19 #endif // RESULT_H
20 
21 namespace Calculator {
22 
23  class StackItem;
24  class StackIteratorPimpl;
25  class StackPimpl;
26  class VariableSet;
27 
28  /*
29  * StackIterator
30  */
31 
32  /** \class StackIterator
33  * \brief Iterator over a Stack from top to bottom
34  */
35  class StackIterator {
36  private:
37  typedef std::shared_ptr<StackIteratorPimpl> PimplPtr;
38 
39  public:
40  /** Equivalent of StackItem::Ptr; */
41  typedef std::shared_ptr<StackItem> StackItemPtr;
42 
43  /** Hint for accessing the value at an iterator */
44  enum class Hint {
45  /** Dereference the next read */
47  /** Do not dereference the next read */
49  };
50 
51  ~StackIterator() = default;
52 
53  /** Create with reference to the variables and the implementint iterator.
54  *
55  * @param thePimpl initial data for the StackIterator
56  */
57  StackIterator(std::shared_ptr<StackIteratorPimpl> thePimpl);
58 
59  StackIterator() = delete;
64 
65  /** Pre-increment: Move to the next position away from the top.
66  *
67  * @return this iterator
68  */
70 
71  /** Post-increment: Move to the next position away from the top, but return the
72  * a copy of this iterator without the modification.
73  *
74  * @return a copy of this iterator before the increment.
75  */
77 
78  /** Return true if this iterator is the same position as rhs.
79  *
80  * @param rhs to compare this iterator to
81  *
82  * @return true if this iterator and rhs refer to the same position, otherwise
83  * false
84  */
85  bool operator==(const StackIterator& rhs) const;
86 
87  /** Return true if this iterator is not the same position as rhs.
88  *
89  * @param rhs to compare this iterator to
90  *
91  * @return false if this iterator and rhs refer to the same position, otherwise
92  * true
93  */
94  bool operator!=(const StackIterator& rhs) const;
95 
96  /** @return false if any errors have been reported, otherwise true */
97  operator bool() const;
98 
99  /** @return the object at the current position as per the current hint and reset
100  * the hint for the next read to Hint::DEREFERENCE_NEXT
101  */
103 
104  /** @return the current item without dereferencing, ignoring the hint entirely
105  */
107 
108  /** Set the current hint for reading the value to theHint.
109  *
110  * @param theHint to set the hint for the next read to
111  *
112  * @return this iterator
113  */
114  StackIterator& setHint(Hint theHint);
115 
116  /** Convenience method to read the current value by operator->* (respecting the
117  * current hint) and return it to a T::Ptr by std::dynamic_pointer_cast. If
118  * the cast fails, the returned value is empty
119  *
120  * @tparam T desired type to cast the value to
121  * @param required if true, conversion failure is logged as a positional
122  * message in the Result.
123  *
124  * @return the current value from operator* as a T::Ptr, which may be empty if
125  * the cast failed
126  */
127  template<typename T>
128  auto as(bool required = true) -> typename T::Ptr {
129  typename T::Ptr asT = std::dynamic_pointer_cast<T, StackItem>(this->operator*());
130  if(required && !asT) {
131  addError(std::string("Value is not ") + T::indef_type_string());
132  }
133  return asT;
134  }
135 
136  /** @return Errors, such as conversion and variable, thus far, if any */
137  const Result& getResult() const;
138 
139  /** Add error message at position
140  *
141  * @param position in the stack the error occurred
142  * @param message describing the error
143  */
144  void addError(unsigned int position, const std::string& message);
145 
146  /** Add error message at current position
147  *
148  * @param message describing the error
149  */
150  void addError(const std::string& message);
151 
152  /** @return the private implementation */
153  PimplPtr getPimpl();
154 
155  private:
156  /** The private implementation */
157  PimplPtr pimpl;
158  };
159 
160  /** Set the iter's hint and return the iter.
161  *
162  * @param iter to set hint on
163  * @param hint to set
164  *
165  * @return iter
166  */
167  StackIterator& operator>>(StackIterator& iter, StackIterator::Hint hint);
168 
169  /** Set t to *iter and return iter.
170  *
171  * @param iter to read from
172  * @param t to set *iter into
173  *
174  * @return iter
175  */
176  StackIterator& operator>>(StackIterator& iter, std::shared_ptr<StackItem>& t);
177 
178  /** Convenience function to read the current value of iter by the template as()
179  * (respecting the current hint) and set to t. If the cast fails in t, the set
180  * value is empty
181  *
182  * @tparam T desired type to cast the value to
183  *
184  * @param iter to read from
185  * @param t to set iter.as<T>() into
186  *
187  * @return iter
188  */
189  template<typename T>
191  t = iter.template as<typename T::element_type>();
192  ++iter;
193  return iter;
194  }
195 
196  /*
197  * Stack
198  */
199 
200  /** Stack of values to process from.
201  *
202  * Contains StackItem::Ptr objects.
203  *
204  * \todo Provide load / save operations.
205  * Provide the ability to write and read Calculator.txt files which will
206  * restore the existing state.
207  */
208  class Stack {
209  private:
210  typedef std::shared_ptr<StackPimpl> PimplPtr;
211  typedef std::shared_ptr<StackItem> StackItemPtr;
212 
213  public:
214  /** Count of StackItems */
215  typedef unsigned int Count;
216 
217  Stack();
218  Stack(const Stack& rhs) = delete;
219  Stack(Stack&& rhs) = delete;
220  Stack& operator=(const Stack& rhs) = delete;
221  Stack& operator=(Stack&& rhs) = delete;
222 
223  /** @return number of StackItems on the Stack */
224  Count getDepth() const;
225 
226  /** @return the VariableSet */
228 
229  /** Reset the stack including pop all variables and reset the variables */
230  void reset();
231 
232  /** Pop all items from the stack */
233  void popAll();
234 
235  /** @return StackIterator at the top of the Stack
236  *
237  * \note This should be a const method; however, the underlying
238  * implementation (STL) would only provide a const_iterator. This would be
239  * just fine for its use; however, std::vector::erase requires a non-const
240  * iterator, which means this must be non-const. I could const cast around
241  * this, but I'll go simpler.
242  */
244 
245  /** @return StackIterator after the bottom of the Stack
246  *
247  * \note This should be a const method; however, the underlying
248  * implementation (STL) would only provide a const_iterator. This would be
249  * just fine for its use; however, std::vector::erase requires a non-const
250  * iterator, which means this must be non-const. I could const cast around
251  * this, but I'll go simpler.
252  */
253  StackIterator end();
254 
255  /** Pop all items after iter on the Stack */
256  void popAfter(StackIterator& iter);
257 
258  /** Push item onto the stack
259  *
260  * @param item to push
261  */
262  void push(StackItemPtr item);
263 
264  /** Create string representation of the current contents of the Stack */
265  std::string toString() const;
266 
267  private:
268  /** The Private Implementation */
269  PimplPtr pimpl;
270  };
271 
272 } // namespace Calculator
273 
274 #endif // STACK_H
Collection of Result information for an operation.
Definition: Result.h:30
Stack of values to process from.
Definition: Stack.h:208
Stack(Stack &&rhs)=delete
StackIterator begin()
Definition: Stack.cpp:221
VariableSet & getVariables()
Definition: Stack.cpp:208
void push(StackItemPtr item)
Push item onto the stack.
Definition: Stack.cpp:241
Stack & operator=(Stack &&rhs)=delete
std::string toString() const
Create string representation of the current contents of the Stack.
Definition: Stack.cpp:245
StackIterator end()
Definition: Stack.cpp:227
void popAfter(StackIterator &iter)
Pop all items after iter on the Stack.
Definition: Stack.cpp:233
Stack(const Stack &rhs)=delete
void popAll()
Pop all items from the stack.
Definition: Stack.cpp:217
void reset()
Reset the stack including pop all variables and reset the variables.
Definition: Stack.cpp:212
Stack & operator=(const Stack &rhs)=delete
Count getDepth() const
Definition: Stack.cpp:204
unsigned int Count
Count of StackItems.
Definition: Stack.h:215
Iterator over a Stack from top to bottom.
Definition: Stack.h:35
Hint
Hint for accessing the value at an iterator.
Definition: Stack.h:44
@ NO_DEREFERENCE_NEXT
Do not dereference the next read.
@ DEREFERENCE_NEXT
Dereference the next read.
auto as(bool required=true) -> typename T::Ptr
Convenience method to read the current value by operator->* (respecting the current hint) and return ...
Definition: Stack.h:128
bool operator!=(const StackIterator &rhs) const
Return true if this iterator is not the same position as rhs.
Definition: Stack.cpp:121
StackIterator & operator=(const StackIterator &)
Definition: Stack.cpp:97
StackIterator & operator=(StackIterator &&)=default
const Result & getResult() const
Definition: Stack.cpp:150
StackIterator & operator++()
Pre-increment: Move to the next position away from the top.
Definition: Stack.cpp:103
StackItemPtr noDereference()
Definition: Stack.cpp:141
StackItemPtr operator*()
Definition: Stack.cpp:129
bool operator==(const StackIterator &rhs) const
Return true if this iterator is the same position as rhs.
Definition: Stack.cpp:117
StackIterator & setHint(Hint theHint)
Set the current hint for reading the value to theHint.
Definition: Stack.cpp:145
StackIterator(StackIterator &&)=default
void addError(unsigned int position, const std::string &message)
Add error message at position.
Definition: Stack.cpp:154
std::shared_ptr< StackItem > StackItemPtr
Equivalent of StackItem::Ptr;.
Definition: Stack.h:41
All variables belonging to a Stack.
Definition: VariableSet.h:28
Container of Calculator resources.
StackIterator & operator>>(StackIterator &iter, StackIterator::Hint hint)
Set the iter's hint and return the iter.
Definition: Stack.cpp:166