Skip to content
Browse files

Fixed the Array and Object classes to avoid undefined behaviours that…

… caused problems when compiling with Visual Studio.
  • Loading branch information...
1 parent 36603da commit e8a9ff1f093f7257272db1a2ed5e8d8621de15a9 @madbranch madbranch committed Jun 30, 2012
Showing with 733 additions and 15 deletions.
  1. +122 −7 include/JsonBox/Array.h
  2. +110 −3 include/JsonBox/Object.h
  3. +58 −5 include/JsonBox/Value.h
  4. +166 −0 src/Array.cpp
  5. +155 −0 src/Object.cpp
  6. +122 −0 src/Value.cpp
View
129 include/JsonBox/Array.h
@@ -2,18 +2,133 @@
#define JB_ARRAY_H
#include <iostream>
-#include <deque>
+#include <vector>
-namespace JsonBox {
- class Value;
+#include "Value.h"
+namespace JsonBox {
/**
- * Represents an array of values in JSON. It's a deque with added methods.
- * So it can be used the same way as a standard STL deque, but can be more
+ * Represents an array of values in JSON. It's a vector with added methods.
+ * So it can be used the same way as a standard STL vector, but can be more
* easily output in a stream.
* @see JsonBox::Value
*/
- typedef std::deque<Value> Array;
+ class Array {
+ public:
+ typedef std::vector<Value> container;
+ typedef container::value_type value_type;
+ typedef container::allocator_type allocator_type;
+ typedef container::size_type size_type;
+ typedef container::difference_type difference_type;
+ typedef container::reference reference;
+ typedef container::const_reference const_reference;
+ typedef container::pointer pointer;
+ typedef container::const_pointer const_pointer;
+ typedef container::iterator iterator;
+ typedef container::const_iterator const_iterator;
+ typedef container::reverse_iterator reverse_iterator;
+ typedef container::const_reverse_iterator const_reverse_iterator;
+
+ Array(const allocator_type &alloc = allocator_type());
+
+ explicit Array(size_type count, const_reference value = value_type(), const allocator_type &alloc = allocator_type());
+
+ template <typename InputIterator>
+ Array(InputIterator first, InputIterator last, const allocator_type &alloc = allocator_type()) : data(first, last) {
+ }
+
+ Array(const Array &other);
+
+ Array &operator=(const Array &other);
+
+ bool operator==(const Array &rhs) const;
+
+ bool operator!=(const Array &rhs) const;
+
+ bool operator<(const Array &rhs) const;
+
+ bool operator<=(const Array &rhs) const;
+
+ bool operator>(const Array &rhs) const;
+
+ bool operator>=(const Array &rhs) const;
+
+ void assign(size_type count, const_reference value);
+
+ template <typename InputIterator>
+ void assign(InputIterator first, InputIterator last) {
+ data.assign(first, last);
+ }
+
+ allocator_type get_allocator() const;
+
+ reference at(size_type pos);
+
+ const_reference at(size_type pos) const;
+
+ reference operator[](size_type pos);
+
+ const_reference operator[](size_type pos) const;
+
+ reference front();
+
+ const_reference front() const;
+
+ reference back();
+
+ const_reference back() const;
+
+ iterator begin();
+
+ const_iterator begin() const;
+
+ iterator end();
+
+ const_iterator end() const;
+
+ reverse_iterator rbegin();
+
+ const_reverse_iterator rbegin() const;
+
+ reverse_iterator rend();
+
+ const_reverse_iterator rend() const;
+
+ bool empty() const;
+
+ size_type size() const;
+
+ size_type max_size() const;
+
+ void reserve(size_type size);
+
+ size_type capacity() const;
+
+ void clear();
+
+ iterator insert(iterator pos, const_reference value);
+
+ void insert(iterator pos, size_type count, const_reference value);
+
+ template <typename InputIterator>
+ void insert(iterator pos, InputIterator first, InputIterator last) {
+ data.insert(pos, first, last);
+ }
+
+ iterator erase(iterator pos);
+
+ iterator erase(iterator first, iterator last);
+
+ void push_back(const_reference value);
+
+ void pop_back();
+
+ void resize(size_type count, const_reference value = value_type());
+
+ void swap(Array &other);
+ private:
+ container data;
+ };
/**
* Output operator overload for the JSON array. Outputs in standard JSON
@@ -22,7 +137,7 @@ namespace JsonBox {
* @param a Array to output into the stream.
* @return Output stream filled with the JSON code.
*/
- std::ostream& operator<<(std::ostream& output, const Array& a);
+ std::ostream &operator<<(std::ostream &output, const Array &a);
}
#endif
View
113 include/JsonBox/Object.h
@@ -5,16 +5,123 @@
#include <map>
#include <string>
-namespace JsonBox {
- class Value;
+#include "Value.h"
+namespace JsonBox {
/**
* Represents a JSON object. It's a map with added methods. So the JSON
* object type can be used the same way as a standard STL map of string and
* Value, but can be more easily output in a stream.
* @see JsonBox::Value
*/
- typedef std::map<std::string, Value> Object;
+ class Object {
+ public:
+ typedef std::map<std::string, Value> container;
+ typedef container::key_type key_type;
+ typedef container::mapped_type mapped_type;
+ typedef container::value_type value_type;
+ typedef container::size_type size_type;
+ typedef container::difference_type difference_type;
+ typedef container::key_compare key_compare;
+ typedef container::allocator_type allocator_type;
+ typedef container::reference reference;
+ typedef container::const_reference const_reference;
+ typedef container::pointer pointer;
+ typedef container::const_pointer const_pointer;
+ typedef container::iterator iterator;
+ typedef container::const_iterator const_iterator;
+ typedef container::reverse_iterator reverse_iterator;
+ typedef container::const_reverse_iterator const_reverse_iterator;
+
+ explicit Object(const key_compare &comp = key_compare(), const allocator_type &alloc = allocator_type());
+
+ template <typename InputIterator>
+ explicit Object(InputIterator first, InputIterator last, const key_compare &comp = key_compare(), const allocator_type &alloc = allocator_type()) : data(first, last, comp, alloc) {
+ }
+
+ Object(const Object &other);
+
+ Object &operator=(const Object &other);
+
+ bool operator==(const Object &rhs) const;
+
+ bool operator!=(const Object &rhs) const;
+
+ bool operator<(const Object &rhs) const;
+
+ bool operator<=(const Object &rhs) const;
+
+ bool operator>(const Object &rhs) const;
+
+ bool operator>=(const Object &rhs) const;
+
+ allocator_type get_allocator() const;
+
+ mapped_type &operator[](const key_type &key);
+
+ iterator begin();
+
+ const_iterator begin() const;
+
+ iterator end();
+
+ const_iterator end() const;
+
+ reverse_iterator rbegin();
+
+ const_reverse_iterator rbegin() const;
+
+ reverse_iterator rend();
+
+ const_reverse_iterator rend() const;
+
+ bool empty() const;
+
+ size_type size() const;
+
+ size_type max_size() const;
+
+ void clear();
+
+ std::pair<iterator, bool> insert(const_reference value);
+
+ iterator insert(iterator hint, const_reference value);
+
+ template <typename InputIterator>
+ void insert(InputIterator first, InputIterator last) {
+ data.insert(first, last);
+ }
+
+ void erase(iterator position);
+
+ void erase(iterator first, iterator last);
+
+ size_type erase(const key_type &key);
+
+ void swap(Object &other);
+
+ size_type count(const key_type &key) const;
+
+ iterator find(const key_type &key);
+
+ const_iterator find(const key_type &key) const;
+
+ std::pair<iterator, iterator> equal_range(const key_type &key);
+
+ std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const;
+
+ iterator lower_bound(const key_type &key);
+
+ const_iterator lower_bound(const key_type &key) const;
+
+ iterator upper_bound(const key_type &key);
+
+ const_iterator upper_bound(const key_type &key) const;
+
+ key_compare key_comp() const;
+ private:
+ container data;
+ };
/**
* Output operator overload for the JSON object. Outputs in standard JSON
View
63 include/JsonBox/Value.h
@@ -7,10 +7,10 @@
#include <string>
#include <iostream>
-#include "Array.h"
-#include "Object.h"
-
namespace JsonBox {
+ class Array;
+ class Object;
+
/**
* Represents a json value. Can be a string, an integer, a floating point
* number, an object, an array, a boolean value or a null value. To put it
@@ -153,6 +153,59 @@ namespace JsonBox {
* @return Reference to the modified value.
*/
Value &operator=(const Value &src);
+
+ /**
+ * Checks if the current value is equal to the right hand side value.
+ * @param rhs Right hand side value to check for equality with.
+ * @return True if the contents of the two values are equal, false if
+ * not.
+ */
+ bool operator==(const Value &rhs) const;
+
+ /**
+ * Checks if the current value is different from the right hand side
+ * value.
+ * @param rhs Right hand side value to check for not equality with.
+ * @return True if the contents of the two values are different, false
+ * if not.
+ */
+ bool operator!=(const Value &rhs) const;
+
+ /**
+ * Checks if the contents of instance are lexicographically less than
+ * the contents of the right hand side value.
+ * @param rhs Right hand side value to check.
+ * @return True if the contents of of the instance are lexicographically
+ * less than the contents of the right hand side value.
+ */
+ bool operator <(const Value &rhs) const;
+
+ /**
+ * Checks if the contents of instance are lexicographically less than or
+ * equal the contents of the right hand side value.
+ * @param rhs Right hand side value to check.
+ * @return True if the contents of of the instance are lexicographically
+ * less than or equal the contents of the right hand side value.
+ */
+ bool operator <=(const Value &rhs) const;
+
+ /**
+ * Checks if the contents of instance are lexicographically greater than
+ * the contents of the right hand side value.
+ * @param rhs Right hand side value to check.
+ * @return True if the contents of of the instance are lexicographically
+ * greater than the contents of the right hand side value.
+ */
+ bool operator >(const Value &rhs) const;
+
+ /**
+ * Checks if the contents of instance are lexicographically greater than
+ * or equal the contents of the right hand side value.
+ * @param rhs Right hand side value to check.
+ * @return True if the contents of of the instance are lexicographically
+ * greater than or equal the contents of the right hand side value.
+ */
+ bool operator >=(const Value &rhs) const;
/**
* Bracket operator overload. If the value doesn't represent an object,
@@ -161,7 +214,7 @@ namespace JsonBox {
* @param key Key identifier of the object's value to get.
* @return Reference to the object's member's value.
*/
- Value &operator[](const Object::key_type &key);
+ Value &operator[](const std::string &key);
/**
* Bracket operator overload. If the value doesn't represent an object,
@@ -183,7 +236,7 @@ namespace JsonBox {
* @param index Index of the value to get.
* @return Reference to the value at the received index in the array.
*/
- Value &operator[](Array::size_type index);
+ Value &operator[](size_t index);
/**
* Gets the value's type.
View
166 src/Array.cpp
@@ -6,6 +6,172 @@
#include <JsonBox/Indenter.h>
namespace JsonBox {
+ Array::Array(const allocator_type &alloc) : data(alloc) {
+ }
+
+ Array::Array(size_type count, const_reference value, const allocator_type &alloc) : data(count, value, alloc) {
+ }
+
+ Array::Array(const Array &other) : data(other.data) {
+ }
+
+ Array &Array::operator=(const Array &other) {
+ data = other.data;
+ return *this;
+ }
+
+ bool Array::operator==(const Array &rhs) const {
+ return data == rhs.data;
+ }
+
+ bool Array::operator!=(const Array &rhs) const {
+ return data != rhs.data;
+ }
+
+ bool Array::operator<(const Array &rhs) const {
+ return data < rhs.data;
+ }
+
+ bool Array::operator<=(const Array &rhs) const {
+ return data <= rhs.data;
+ }
+
+ bool Array::operator>(const Array &rhs) const {
+ return data > rhs.data;
+ }
+
+ bool Array::operator>=(const Array &rhs) const {
+ return data >= rhs.data;
+ }
+
+ void Array::assign(size_type count, const_reference value) {
+ data.assign(count, value);
+ }
+
+ Array::allocator_type Array::get_allocator() const {
+ return data.get_allocator();
+ }
+
+ Array::reference Array::at(size_type pos) {
+ return data.at(pos);
+ }
+
+ Array::const_reference Array::at(size_type pos) const {
+ return data.at(pos);
+ }
+
+ Array::reference Array::operator[](size_type pos) {
+ return data[pos];
+ }
+
+ Array::const_reference Array::operator[](size_type pos) const {
+ return data[pos];
+ }
+
+ Array::reference Array::front() {
+ return data.front();
+ }
+
+ Array::const_reference Array::front() const {
+ return data.front();
+ }
+
+ Array::reference Array::back() {
+ return data.back();
+ }
+
+ Array::const_reference Array::back() const {
+ return data.back();
+ }
+
+ Array::iterator Array::begin() {
+ return data.begin();
+ }
+
+ Array::const_iterator Array::begin() const {
+ return data.begin();
+ }
+
+ Array::iterator Array::end() {
+ return data.end();
+ }
+
+ Array::const_iterator Array::end() const {
+ return data.end();
+ }
+
+ Array::reverse_iterator Array::rbegin() {
+ return data.rbegin();
+ }
+
+ Array::const_reverse_iterator Array::rbegin() const {
+ return data.rbegin();
+ }
+
+ Array::reverse_iterator Array::rend() {
+ return data.rend();
+ }
+
+ Array::const_reverse_iterator Array::rend() const {
+ return data.rend();
+ }
+
+ bool Array::empty() const {
+ return data.empty();
+ }
+
+ Array::size_type Array::size() const {
+ return data.size();
+ }
+
+ Array::size_type Array::max_size() const {
+ return data.max_size();
+ }
+
+ void Array::reserve(size_type size) {
+ data.reserve(size);
+ }
+
+ Array::size_type Array::capacity() const {
+ return data.capacity();
+ }
+
+ void Array::clear() {
+ data.clear();
+ }
+
+ Array::iterator Array::insert(iterator pos, const_reference value) {
+ return data.insert(pos, value);
+ }
+
+ void Array::insert(iterator pos, size_type count, const_reference value) {
+ data.insert(pos, count, value);
+ }
+
+ Array::iterator Array::erase(iterator pos) {
+ return data.erase(pos);
+ }
+
+ Array::iterator Array::erase(iterator first, iterator last) {
+ return data.erase(first, last);
+ }
+
+ void Array::push_back(const_reference value) {
+ data.push_back(value);
+ }
+
+ void Array::pop_back() {
+ data.pop_back();
+ }
+
+ void Array::resize(size_type count, const_reference value) {
+ data.resize(count, value);
+ }
+
+ void Array::swap(Array &other) {
+ data.swap(other.data);
+ }
+
std::ostream &operator<<(std::ostream &output, const Array &a) {
if (a.empty()) {
output << Structural::BEGIN_ARRAY << Structural::END_ARRAY;
View
155 src/Object.cpp
@@ -6,6 +6,161 @@
#include <JsonBox/Indenter.h>
namespace JsonBox {
+ Object::Object(const key_compare &comp, const allocator_type &alloc) : data(comp, alloc) {
+ }
+
+ Object::Object(const Object &other) : data(other.data) {
+ }
+
+ Object &Object::operator=(const Object &other) {
+ data = other.data;
+ return *this;
+ }
+
+ bool Object::operator==(const Object &rhs) const {
+ return data == rhs.data;
+ }
+
+ bool Object::operator!=(const Object &rhs) const {
+ return data != rhs.data;
+ }
+
+ bool Object::operator<(const Object &rhs) const {
+ return data < rhs.data;
+ }
+
+ bool Object::operator<=(const Object &rhs) const {
+ return data <= rhs.data;
+ }
+
+ bool Object::operator>(const Object &rhs) const {
+ return data > rhs.data;
+ }
+
+ bool Object::operator>=(const Object &rhs) const {
+ return data >= rhs.data;
+ }
+
+ Object::allocator_type Object::get_allocator() const {
+ return data.get_allocator();
+ }
+
+ Object::mapped_type &Object::operator[](const key_type &key) {
+ return data[key];
+ }
+
+ Object::iterator Object::begin() {
+ return data.begin();
+ }
+
+ Object::const_iterator Object::begin() const {
+ return data.begin();
+ }
+
+ Object::iterator Object::end() {
+ return data.end();
+ }
+
+ Object::const_iterator Object::end() const {
+ return data.end();
+ }
+
+ Object::reverse_iterator Object::rbegin() {
+ return data.rbegin();
+ }
+
+ Object::const_reverse_iterator Object::rbegin() const {
+ return data.rbegin();
+ }
+
+ Object::reverse_iterator Object::rend() {
+ return data.rend();
+ }
+
+ Object::const_reverse_iterator Object::rend() const {
+ return data.rend();
+ }
+
+ bool Object::empty() const {
+ return data.empty();
+ }
+
+ Object::size_type Object::size() const {
+ return data.size();
+ }
+
+ Object::size_type Object::max_size() const {
+ return data.max_size();
+ }
+
+ void Object::clear() {
+ data.clear();
+ }
+
+ std::pair<Object::iterator, bool> Object::insert(const_reference value) {
+ return data.insert(value);
+ }
+
+ Object::iterator Object::insert(iterator hint, const_reference value) {
+ return data.insert(hint, value);
+ }
+
+ void Object::erase(iterator position) {
+ data.erase(position);
+ }
+
+ void Object::erase(iterator first, iterator last) {
+ data.erase(first, last);
+ }
+
+ Object::size_type Object::erase(const key_type &key) {
+ return data.erase(key);
+ }
+
+ void Object::swap(Object &other) {
+ data.swap(other.data);
+ }
+
+ Object::size_type Object::count(const key_type &key) const {
+ return data.count(key);
+ }
+
+ Object::iterator Object::find(const key_type &key) {
+ return data.find(key);
+ }
+
+ Object::const_iterator Object::find(const key_type &key) const {
+ return data.find(key);
+ }
+
+ std::pair<Object::iterator, Object::iterator> Object::equal_range(const key_type &key) {
+ return data.equal_range(key);
+ }
+
+ std::pair<Object::const_iterator, Object::const_iterator> Object::equal_range(const key_type &key) const {
+ return data.equal_range(key);
+ }
+
+ Object::iterator Object::lower_bound(const key_type &key) {
+ return data.lower_bound(key);
+ }
+
+ Object::const_iterator Object::lower_bound(const key_type &key) const {
+ return data.lower_bound(key);
+ }
+
+ Object::iterator Object::upper_bound(const key_type &key) {
+ return data.upper_bound(key);
+ }
+
+ Object::const_iterator Object::upper_bound(const key_type &key) const {
+ return data.upper_bound(key);
+ }
+
+ Object::key_compare Object::key_comp() const {
+ return data.key_comp();
+ }
+
std::ostream &operator<<(std::ostream &output, const Object &o) {
// If the object is empty, we simply write "{}".
if (o.empty()) {
View
122 src/Value.cpp
@@ -12,6 +12,8 @@
#include <JsonBox/OutputFilter.h>
#include <JsonBox/IndentCanceller.h>
#include <JsonBox/SolidusEscaper.h>
+#include <JsonBox/Array.h>
+#include <JsonBox/Object.h>
namespace JsonBox {
@@ -217,6 +219,126 @@ namespace JsonBox {
return *this;
}
+
+ bool Value::operator==(const Value &rhs) const {
+ if (type == rhs.type) {
+ switch (type) {
+ case STRING:
+ return *data.stringValue == *data.stringValue;
+ break;
+
+ case INTEGER:
+ return *data.intValue == *data.intValue;
+ break;
+
+ case DOUBLE:
+ return *data.doubleValue == *data.doubleValue;
+ break;
+
+ case OBJECT:
+ return *data.objectValue == *data.objectValue;
+ break;
+
+ case ARRAY:
+ return *data.arrayValue == *data.arrayValue;
+ break;
+
+ case BOOLEAN:
+ return *data.boolValue == *data.boolValue;
+ break;
+
+ default:
+ return true;
+ break;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ bool Value::operator!=(const Value &rhs) const {
+ return !(*this == rhs);
+ }
+
+ bool Value::operator<(const Value &rhs) const {
+ if (type == rhs.type) {
+ switch (type) {
+ case STRING:
+ return *data.stringValue < *data.stringValue;
+ break;
+
+ case INTEGER:
+ return *data.intValue < *data.intValue;
+ break;
+
+ case DOUBLE:
+ return *data.doubleValue < *data.doubleValue;
+ break;
+
+ case OBJECT:
+ return *data.objectValue < *data.objectValue;
+ break;
+
+ case ARRAY:
+ return *data.arrayValue < *data.arrayValue;
+ break;
+
+ case BOOLEAN:
+ return *data.boolValue < *data.boolValue;
+ break;
+
+ default:
+ return false;
+ break;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ bool Value::operator<=(const Value &rhs) const {
+ return *this < rhs || *this == rhs;
+ }
+
+ bool Value::operator>(const Value &rhs) const {
+ if (type == rhs.type) {
+ switch (type) {
+ case STRING:
+ return *data.stringValue > *data.stringValue;
+ break;
+
+ case INTEGER:
+ return *data.intValue > *data.intValue;
+ break;
+
+ case DOUBLE:
+ return *data.doubleValue > *data.doubleValue;
+ break;
+
+ case OBJECT:
+ return *data.objectValue > *data.objectValue;
+ break;
+
+ case ARRAY:
+ return *data.arrayValue > *data.arrayValue;
+ break;
+
+ case BOOLEAN:
+ return *data.boolValue > *data.boolValue;
+ break;
+
+ default:
+ return false;
+ break;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ bool Value::operator>=(const Value &rhs) const {
+ return *this > rhs || *this == rhs;
+ }
Value &Value::operator[](const Object::key_type &key) {
if (type != OBJECT) {

0 comments on commit e8a9ff1

Please sign in to comment.
Something went wrong with that request. Please try again.