Commit 7c2192bb authored by Takhir Fakhrutdinov's avatar Takhir Fakhrutdinov

Инициализация репозитория

parent e05bedd4
*
!.gitignore
!makefile
!readme.md
!Makefile
!include/
!fson/
PLATFORM=$(shell uname -s |awk -F- '{print $$1}')
SRC=src
LIB=../build/$(PLATFORM)/lib
BUILD=../build/$(PLATFORM)/obj/json
TEST=../build/$(PLATFORM)/test
MODDIR=../build/$(PLATFORM)/mod
F95=.f95
OBJ=.o
FC = gfortran
FCFLAGS = -O2 -fbounds-check -O -Wall
FCFLAGS += $(FCEXTRA)
FMFLAGS = -J$(MODDIR)
ifeq ($(PLATFORM),$(filter $(PLATFORM),Darwin Linux))
LDFLAGS=-lsofa -L$(LIB)
else
LDFLAGS = -lfson -L$(LIB) -rpath /usr/local/lib/gcc48
endif
LDFLAGS += $(FCEXTRA)
AR = ar
ARFLAGS= ru
ifeq ($(PLATFORM),MINGW32_NT)
EXE=.exe
LIBTARGET=$(LIB)/libfson.a
else
EXE=
# FCFLAGS += -fPIC
ifeq ($(PLATFORM),Darwin)
LIBTARGET=$(LIB)/libfson.a
else
LIBTARGET=$(LIB)/libfson.a
endif
endif
# "make" builds all
all: dirs lib
dirs:
mkdir -p $(LIB) $(BUILD) $(TEST) $(MODDIR)
# List of example programs
EXAMPLES = basic example1
RMEXAS = $(patsubst %, $(TEST)/%$(EXE), $(EXAMPLES))
RMEXASD = $(patsubst %, $(TEST)/%$(EXE).dSym, $(EXAMPLES))
examples: $(patsubst %, $(TEST)/%$(EXE), $(EXAMPLES)) json
JSON = $(shell find src/test -name '*.json')
RMJ = $(patsubst $(SRC)/test%, $(TEST)%, $(JSON))
json: $(patsubst $(SRC)/test%, $(TEST)%, $(JSON))
FSON = fson_string_m fson_value_m fson_path_m fson
OBJECTS = $(patsubst %, $(BUILD)/%.o, $(FSON))
MODS = $(patsubst %, $(MODDIR)/%.mod, $(FSON))
lib: $(LIBTARGET)
$(LIBTARGET) : $(OBJECTS)
$(AR) $(ARFLAGS) $(LIBTARGET) $(OBJECTS)
$(TEST)%.json : $(SRC)/test%.json
cp -f $< $@
#$(LIB)%$(EXE) : $(BUILD)/%$(OBJ) $(OBJECTS)
# $(FC) $(FCFLAGS) -o $@ $^ $(LDFLAGS)
$(TEST)%$(EXE) : $(SRC)/test%$(F95)
$(FC) $(FCFLAGS) -o $@ $^ $(LDFLAGS) $(FMFLAGS)
$(BUILD)/%$(OBJ): $(SRC)/%$(F95)
$(FC) $(FCFLAGS) $(FMFLAGS) -c $< -o $@
test:
$(info test fson...)
clean:
rm -rf $(OBJECTS) $(LIBTARGET) $(MODS) $(RMEXAS) $(RMEXASD) $(RMJ)
This diff is collapsed.
This diff is collapsed.
! Copyright (c) 2012 Joseph A. Levin
!
! Permission is hereby granted, free of charge, to any person obtaining a copy of this
! software and associated documentation files (the "Software"), to deal in the Software
! without restriction, including without limitation the rights to use, copy, modify, merge,
! publish, distribute, sublicense, and/or sell copies of the Software, and to permit
! persons to whom the Software is furnished to do so, subject to the following conditions:
!
! The above copyright notice and this permission notice shall be included in all copies or
! substantial portions of the Software.
!
! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
! INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
! PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
! LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
! OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
! DEALINGS IN THE SOFTWARE.
!
! File: string.f95
! Author: josephalevin
!
! Created on March 7, 2012, 7:40 PM
!
module fson_string_m
private
public :: fson_string, fson_string_create, fson_string_destroy, fson_string_length, fson_string_append, fson_string_clear
public :: fson_string_equals, fson_string_copy
integer, parameter :: BLOCK_SIZE = 32
type fson_string
character (len = BLOCK_SIZE) :: chars
integer :: index = 0
type(fson_string), pointer :: next => null()
end type fson_string
interface fson_string_append
module procedure append_chars, append_string
end interface fson_string_append
interface fson_string_copy
module procedure copy_chars
end interface fson_string_copy
interface fson_string_equals
module procedure equals_string
end interface fson_string_equals
interface fson_string_length
module procedure string_length
end interface fson_string_length
contains
!
! FSON STRING CREATE
!
function fson_string_create(chars) result(new)
character(len=*), optional :: chars
type(fson_string), pointer :: new
allocate(new)
! append chars if available
if(present(chars)) then
call append_chars(new, chars)
endif
end function fson_string_create
!
! FSON STRING CREATE
!
recursive subroutine fson_string_destroy(this)
type(fson_string), pointer :: this
if(associated(this % next)) then
call fson_string_destroy(this % next)
endif
nullify (this % next)
nullify (this)
end subroutine fson_string_destroy
!
! ALLOCATE BLOCK
!
subroutine allocate_block(this)
type(fson_string), pointer :: this
type(fson_string), pointer :: new
if (.not.associated(this % next)) then
allocate(new)
this % next => new
endif
end subroutine allocate_block
!
! APPEND_STRING
!
subroutine append_string(str1, str2)
type(fson_string), pointer :: str1, str2
integer length, i
length = string_length(str2)
do i = 1, length
call append_char(str1, get_char_at(str2, i))
enddo
end subroutine append_string
!
! APPEND_CHARS
!
subroutine append_chars(str, c)
type(fson_string), pointer :: str
character (len = *), intent(in) :: c
integer length, i
length = len(c)
do i = 1, length
call append_char(str, c(i:i))
enddo
end subroutine append_chars
!
! APPEND_CHAR
!
recursive subroutine append_char(str, c)
type(fson_string), pointer :: str
character, intent(in) :: c
if (str % index .GE. BLOCK_SIZE) then
!set down the chain
call allocate_block(str)
call append_char(str % next, c)
else
! set local
str % index = str % index + 1
str % chars(str % index:str % index) = c
endif
end subroutine append_char
!
! COPY CHARS
!
subroutine copy_chars(this, to)
type(fson_string), pointer :: this
character(len = *), intent(inout) :: to
integer :: length
length = min(string_length(this), len(to))
do i = 1, length
to(i:i) = get_char_at(this, i)
enddo
! pad with nothing
do i = length + 1, len(to)
to(i:i) = ""
enddo
end subroutine copy_chars
!
! CLEAR
!
recursive subroutine string_clear(this)
type(fson_string), pointer :: this
if (associated(this % next)) then
call string_clear(this % next)
deallocate(this % next)
nullify (this % next)
endif
this % index = 0
end subroutine string_clear
!
! SIZE
!
recursive integer function string_length(str) result(count)
type(fson_string), pointer :: str
count = str % index
if (str % index == BLOCK_SIZE .AND. associated(str % next)) then
count = count + string_length(str % next)
endif
end function string_length
!
! GET CHAR AT
!
recursive character function get_char_at(this, i) result(c)
type(fson_string), pointer :: this
integer, intent(in) :: i
if (i .LE. this % index) then
c = this % chars(i:i)
else
c = get_char_at(this % next, i - this % index)
endif
end function get_char_at
!
! EQUALS STRING
!
logical function equals_string(this, other) result(equals)
type(fson_string), pointer :: this, other
integer :: i
equals = .false.
if(fson_string_length(this) .ne. fson_string_length(other)) then
equals = .false.
return
else if(fson_string_length(this) == 0) then
equals = .true.
return
endif
do i=1, fson_string_length(this)
if(get_char_at(this, i) .ne. get_char_at(other, i)) then
equals = .false.
return
endif
enddo
equals = .true.
end function equals_string
end module fson_string_m
This diff is collapsed.
! Copyright (c) 2012 Joseph A. Levin
!
! Permission is hereby granted, free of charge, to any person obtaining a copy of this
! software and associated documentation files (the "Software"), to deal in the Software
! without restriction, including without limitation the rights to use, copy, modify, merge,
! publish, distribute, sublicense, and/or sell copies of the Software, and to permit
! persons to whom the Software is furnished to do so, subject to the following conditions:
!
! The above copyright notice and this permission notice shall be included in all copies or
! substantial portions of the Software.
!
! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
! INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
! PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
! LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
! OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
! DEALINGS IN THE SOFTWARE.
! FSON MODULE
!
! File: fson.f95
! Author: Joseph A. Levin
!
! Created on January 8, 2013
!
program example_basic
! Typical usage should only require an explicit use of the fson module.
! The other modules will be used privatley by fson as required.
! use fson
! declare a pointer variable. Always use a pointer with fson_value.
! type(fson_value), pointer :: value
! parse the json file
! value => fson_parse("test1.json")
! print the parsed data to the console
! call fson_print(value)
! extract data from the parsed value
! clean up
! call fson_destroy(value)
end program example_basic
! Copyright (c) 2012 Joseph A. Levin
!
! Permission is hereby granted, free of charge, to any person obtaining a copy of this
! software and associated documentation files (the "Software"), to deal in the Software
! without restriction, including without limitation the rights to use, copy, modify, merge,
! publish, distribute, sublicense, and/or sell copies of the Software, and to permit
! persons to whom the Software is furnished to do so, subject to the following conditions:
!
! The above copyright notice and this permission notice shall be included in all copies or
! substantial portions of the Software.
!
! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
! INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
! PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
! LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
! OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
! DEALINGS IN THE SOFTWARE.
! FSON MODULE
!
! File: fson.f95
! Author: Joseph A. Levin
!
! Created on March 10, 2012, 5:24 AM
!
program example1
! Typical usage should only require an explicit use of the fson module.
! The other modules will be used privatley by fson as required.
use fson
! declare a pointer variable. Always use a pointer with fson_value.
type(fson_value), pointer :: value
! parse the json file
value => fson_parse("test1.json")
! print the parsed data to the console
call fson_print(value)
! extract data from the parsed value
! clean up
call fson_destroy(value)
end program example1
\ No newline at end of file
{
"firstName": "John",
"lastName" : "Smith",
"age" : 25,
"friend" : true,
"password" : null,
"address" :
{
"streetAddress": "21 2nd Street",
"city" : "New York",
"state" : "NY",
"postalCode" : "10021"
},
"phoneNumber":
[
{
"type" : "home",
"number": "212 555-1234"
},
{
"type" : "fax",
"number": "646 555-4567"
}
]
}
\ No newline at end of file
*
!.gitignore
!*.h
!*.hpp
!*.tcc
!cpp-json/
\ No newline at end of file
#ifndef ARRAY_20110526_H_
#define ARRAY_20110526_H_
namespace json {
class array;
class value;
class array {
friend bool operator==(const array &lhs, const array &rhs);
friend bool operator!=(const array &lhs, const array &rhs);
template <class In>
friend class parser;
private:
using C = std::vector<value>;
public:
using allocator_type = typename C::allocator_type;
using reference = typename C::reference;
using const_reference = typename C::const_reference;
using pointer = typename C::pointer;
using const_pointer = typename C::const_pointer;
using iterator = typename C::iterator;
using const_iterator = typename C::const_iterator;
using reverse_iterator = typename C::reverse_iterator;
using const_reverse_iterator = typename C::const_reverse_iterator;
using difference_type = typename C::difference_type;
using size_type = typename C::size_type;
public:
array() = default;
array(array &&other) = default;
array(const array &other) = default;
array &operator=(array &&rhs) = default;
array &operator=(const array &rhs) = default;
array(std::initializer_list<value> list);
public:
// Added by fte...
reference front() { return values_.front(); }
reference back() { return values_.back(); }
const_reference front() const { return values_.front(); }
const_reference back() const { return values_.back(); }
iterator erase (const_iterator position) { return values_.erase(position); }
iterator erase (const_iterator first, const_iterator last) { return values_.erase(first,last); }
// Added by fte...
iterator begin() { return values_.begin(); }
iterator end() { return values_.end(); }
const_iterator begin() const { return values_.begin(); }
const_iterator end() const { return values_.end(); }
const_iterator cbegin() const { return values_.begin(); }
const_iterator cend() const { return values_.end(); }
reverse_iterator rbegin() { return values_.rbegin(); }
reverse_iterator rend() { return values_.rend(); }
const_reverse_iterator rbegin() const { return values_.rbegin(); }
const_reverse_iterator rend() const { return values_.rend(); }
const_reverse_iterator crbegin() const { return values_.rbegin(); }
const_reverse_iterator crend() const { return values_.rend(); }
public:
size_type size() const { return values_.size(); }
size_type max_size() const { return values_.max_size(); }
bool empty() const { return values_.empty(); }
// Added by fte...
void resize (size_type n) { values_.resize(n); }
void clear() noexcept { values_.clear(); }
// Added by fte...
public:
const value operator[](std::size_t n) const;
value &operator[](std::size_t n);
const value at(std::size_t n) const;
value &at(std::size_t n);
public:
template <class T, class... Args>
array &append(const T &v, Args &&...args);
template <class T>
array &append(T &&v);
template <class T>
array &append(const T &v);
public:
void swap(array &other);
private:
C values_;
};
bool operator==(const array &lhs, const array &rhs);
bool operator!=(const array &lhs, const array &rhs);
inline array::iterator begin(array &arr) { return arr.begin(); }
inline array::iterator end(array &arr) { return arr.end(); }
inline array::const_iterator begin(const array &arr) { return arr.begin(); }
inline array::const_iterator end(const array &arr) { return arr.end(); }
inline array::const_iterator cbegin(const array &arr) { return arr.begin(); }
inline array::const_iterator cend(const array &arr) { return arr.end(); }
inline array::reverse_iterator rbegin(array &arr) { return arr.rbegin(); }
inline array::reverse_iterator rend(array &arr) { return arr.rend(); }
inline array::const_reverse_iterator rbegin(const array &arr) { return arr.rbegin(); }
inline array::const_reverse_iterator rend(const array &arr) { return arr.rend(); }
inline array::const_reverse_iterator crbegin(const array &arr) { return arr.rbegin(); }
inline array::const_reverse_iterator crend(const array &arr) { return arr.rend(); }
}
#endif
#ifndef ARRAY_20120424_TCC_
#define ARRAY_20120424_TCC_
namespace json {
//------------------------------------------------------------------------------
// Name: array
//------------------------------------------------------------------------------
inline array::array(std::initializer_list<value> list) {
for(const auto &x : list) {
values_.emplace_back(x);
}
}
//------------------------------------------------------------------------------
// Name: append
//------------------------------------------------------------------------------
template <class T, class... Args>
array &array::append(const T &v, Args &&...args) {
values_.push_back(value(v));
return append(args...);
}
//------------------------------------------------------------------------------
// Name: append
//------------------------------------------------------------------------------
template <class T>
array &array::append(T &&v) {
values_.push_back(value(std::move(v)));
return *this;
}
//------------------------------------------------------------------------------
// Name: operator[]
//------------------------------------------------------------------------------
inline const value array::operator[](std::size_t n) const {
return at(n);
}
//------------------------------------------------------------------------------
// Name: operator[]
//------------------------------------------------------------------------------
inline value &array::operator[](std::size_t n) {
return at(n);
}
//------------------------------------------------------------------------------
// Name: at
//------------------------------------------------------------------------------
inline const value array::at(std::size_t n) const {
if(n < values_.size()) {
return values_[n];
}
throw invalid_index();
}
//------------------------------------------------------------------------------
// Name: at
//------------------------------------------------------------------------------
inline value &array::at(std::size_t n) {
if(n < values_.size()) {
return values_[n];
}
throw invalid_index();
}
//------------------------------------------------------------------------------
// Name: append
//------------------------------------------------------------------------------
template <class T>
array &array::append(const T &v) {
values_.push_back(value(v));
return *this;
}
//------------------------------------------------------------------------------
// Name: swap
//------------------------------------------------------------------------------
inline void array::swap(array &other) {
using std::swap;
swap(values_, other.values_);
}
//------------------------------------------------------------------------------
// Name: operator==
//------------------------------------------------------------------------------
inline bool operator==(const array &lhs, const array &rhs) {
if(lhs.values_.size() == rhs.values_.size()) {
return lhs.values_ == rhs.values_;
}
return false;
}
//------------------------------------------------------------------------------
// Name: operator!=
//------------------------------------------------------------------------------
inline bool operator!=(const array &lhs, const array &rhs) {
return !(lhs == rhs);
}
}
#endif
#ifndef EXCEPTION_20120104_H_
#define EXCEPTION_20120104_H_
namespace json {
// general error
class exception : public std::exception {
public:
exception() : location(-1) {
}
public:
int location;
};
// parsing errors
class boolean_expected : public exception {};
class brace_expected : public exception {};
class bracket_expected : public exception {};
class colon_expected : public exception {};
class hex_character_expected : public exception {};
class quote_expected : public exception {};
class invalid_unicode_character : public exception {};
class keyword_expected : public exception {};
class string_expected : public exception {};
class value_expected : public exception {};
class utf16_surrogate_expected : public exception {};
class invalid_number : public exception {};
class invalid_utf8_string : public exception {};
// usage errors
class invalid_type_cast : public exception {};
class invalid_index : public exception {};
}
#endif
#ifndef JSON_20110525_H_
#define JSON_20110525_H_
/* TODO(eteran): support unicode
00 00 00 xx UTF-32BE
00 xx 00 xx UTF-16BE
xx 00 00 00 UTF-32LE
xx 00 xx 00 UTF-16LE
xx xx xx xx UTF-8
*/
#include <algorithm>
#include <cctype>
#include <cstdint>
#include <exception>
#include <initializer_list>
#include <iostream>
#include <iterator>
#include <memory>
#include <sstream>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <vector>
namespace json {
class value;
class array;
class object;
using object_pointer = std::shared_ptr<object>;
using array_pointer = std::shared_ptr<array>;
// type testing
inline bool is_string(const value &v);
inline bool is_bool(const value &v);
inline bool is_number(const value &v);
inline bool is_object(const value &v);
inline bool is_array(const value &v);
inline bool is_null(const value &v);
// conversion (you get a copy)
inline std::string to_string(const value &v);
inline bool to_bool(const value &v);
inline double to_number(const value &v);
inline int64_t to_integer(const value &v);
inline object to_object(const value &v);
inline array to_array(const value &v);
// interpretation (you get a reference)
inline object &as_object(value &v);
inline array &as_array(value &v);
inline std::string &as_string(value &v);
inline const object &as_object(const value &v);
inline const array &as_array(const value &v);
inline const std::string &as_string(const value &v);
// does the given object have a given key?
inline bool has_key(const value &v, const std::string &key);
inline bool has_key(const object &o, const std::string &key);
// create a value from some JSON
template <class In>
inline value parse(In first, In last);
inline value parse(std::istream &is);
inline value parse(std::istream &&is);
inline value parse(const std::string &s);
// convert a value to a JSON string
enum {
ESCAPE_UNICODE = 0x01,
PRETTY_PRINT = 0x02
};
inline std::string stringify(const value &v, unsigned options);
inline std::string stringify(const array &a, unsigned options);
inline std::string stringify(const object &o, unsigned options);
inline std::string stringify(const value &v);
inline std::string stringify(const array &a);
inline std::string stringify(const object &o);
}
#include "exception.h"
#include "value.h"
#include "object.h"
#include "array.h"
#include "parser.h"
#include "json.tcc"
#include "object.tcc"
#include "array.tcc"
#include "value.tcc"
#include "parser.tcc"
#endif
This diff is collapsed.
#ifndef OBJECT_20110526_H_
#define OBJECT_20110526_H_
namespace json {
class object;
class value;
class object {
friend bool operator==(const object &lhs, const object &rhs);
friend bool operator!=(const object &lhs, const object &rhs);
template <class In>
friend class parser;
private:
#ifdef ORDERED_DICT
using C = std::vector<std::pair<std::string, value>>;
#else
using C = std::unordered_map<std::string, value>;
#endif
public:
using allocator_type = typename C::allocator_type;
using reference = typename C::reference;
using const_reference = typename C::const_reference;
using pointer = typename C::pointer;
using const_pointer = typename C::const_pointer;
using iterator = typename C::iterator;
using const_iterator = typename C::const_iterator;
using difference_type = typename C::difference_type;
using size_type = typename C::size_type;
public:
object() = default;
object(const object &other) = default;
object(object &&other) = default;
object &operator=(const object &rhs) = default;
object &operator=(object &&rhs) = default;
object(std::initializer_list<std::pair<std::string, value>> list);
public:
iterator begin() { return values_.begin(); }
iterator end() { return values_.end(); }
const_iterator begin() const { return values_.begin(); }
const_iterator end() const { return values_.end(); }
const_iterator cbegin() const { return values_.begin(); }
const_iterator cend() const { return values_.end(); }
public:
#ifdef ORDERED_DICT
iterator find(const std::string &s) {
return std::find_if(values_.begin(), values_.end(), [&s](const std::pair<std::string, value> &entry) {
return entry.first == s;
});
}
const_iterator find(const std::string &s) const {
return std::find_if(values_.begin(), values_.end(), [&s](const std::pair<std::string, value> &entry) {
return entry.first == s;
});
}
#else
iterator find(const std::string &s) { return values_.find(s); }
const_iterator find(const std::string &s) const { return values_.find(s); }
#endif
public:
size_type size() const { return values_.size(); }
size_type max_size() const { return values_.max_size(); }
bool empty() const { return values_.empty(); }
// Added by fte...
void clear() noexcept { values_.clear(); }
// Added by fte...
public:
const value operator[](const std::string &key) const;
value &operator[](const std::string &key);
const value at(const std::string &key) const;
value &at(const std::string &key);
template <class T>
object &insert(const std::string &key, const T &v);
template <class T>
object &insert(const std::pair<std::string, T> &p);
template <class T>
object &insert(std::pair<std::string, T> &&p);
public:
void swap(object &other);
private:
C values_;
};
bool operator==(const object &lhs, const object &rhs);
bool operator!=(const object &lhs, const object &rhs);
inline object::iterator begin(object &obj) { return obj.begin(); }
inline object::iterator end(object &obj) { return obj.end(); }
inline object::const_iterator begin(const object &obj) { return obj.begin(); }
inline object::const_iterator end(const object &obj) { return obj.end(); }
inline object::const_iterator cbegin(const object &obj) { return obj.begin(); }
inline object::const_iterator cend(const object &obj) { return obj.end(); }
}
#endif
#ifndef OBJECT_20120424_TCC_
#define OBJECT_20120424_TCC_
namespace json {
//------------------------------------------------------------------------------
// Name: object
//------------------------------------------------------------------------------
inline object::object(std::initializer_list<std::pair<std::string, value>> list) {
for(auto &x : list) {
#ifdef ORDERED_DICT
values_.emplace_back(x);
#else
values_.emplace(x.first, x.second);
#endif
}
}
//------------------------------------------------------------------------------
// Name: insert
//------------------------------------------------------------------------------
template <class T>
inline object &object::insert(std::pair<std::string, T> &&p) {
#ifdef ORDERED_DICT
values_.emplace_back(std::move(p));
#else
values_.insert(std::move(p));
#endif
return *this;
}
//------------------------------------------------------------------------------
// Name: operator[]
//------------------------------------------------------------------------------
inline const value object::operator[](const std::string &key) const {
return at(key);
}
//------------------------------------------------------------------------------
// Name: operator[]
//------------------------------------------------------------------------------
inline value &object::operator[](const std::string &key) {
return at(key);
}
//------------------------------------------------------------------------------
// Name: at
//------------------------------------------------------------------------------
inline const value object::at(const std::string &key) const {
#ifdef ORDERED_DICT
auto it = std::find_if(values_.begin(), values_.end(), [&key](const std::pair<std::string, value> &entry) {
return entry.first == key;
});
#else
auto it = values_.find(key);
#endif
if(it != values_.end()) {
return it->second;
}
throw invalid_index();
}
//------------------------------------------------------------------------------
// Name: at
//------------------------------------------------------------------------------
inline value &object::at(const std::string &key) {
#ifdef ORDERED_DICT
auto it = std::find_if(values_.begin(), values_.end(), [&key](const std::pair<std::string, value> &entry) {
return entry.first == key;
});
#else
auto it = values_.find(key);
#endif
if(it != values_.end()) {
return it->second;
}
throw invalid_index();
}
//------------------------------------------------------------------------------
// Name: insert
//------------------------------------------------------------------------------
template <class T>
inline object &object::insert(const std::pair<std::string, T> &p) {
#ifdef ORDERED_DICT
values_.emplace_back(p);
#else
values_.insert(p);
#endif
return *this;
}
//------------------------------------------------------------------------------
// Name: insert
//------------------------------------------------------------------------------
template <class T>
inline object &object::insert(const std::string &key, const T &v) {
#ifdef ORDERED_DICT
values_.emplace_back(std::make_pair(key, value(v)));
return *this;
#else
return insert(std::make_pair(key, value(v)));
#endif
}
//------------------------------------------------------------------------------
// Name: swap
//------------------------------------------------------------------------------
inline void object::swap(object &other) {
using std::swap;
swap(values_, other.values_);
}
//------------------------------------------------------------------------------
// Name: operator==
//------------------------------------------------------------------------------
inline bool operator==(const object &lhs, const object &rhs) {
if(lhs.values_.size() == rhs.values_.size()) {
return lhs.values_ == rhs.values_;
}
return false;
}
//------------------------------------------------------------------------------
// Name: operator!=
//------------------------------------------------------------------------------
inline bool operator!=(const object &lhs, const object &rhs) {
return !(lhs == rhs);
}
}
#endif
#ifndef PARSER_20140115_H_
#define PARSER_20140115_H_
namespace json {
class value;
template <class In>
class parser {
public:
parser(In first, In last);
public:
value parse();
public:
const In begin() const { return begin_; }
const In end() const { return end_; }
In current() const { return cur_; }
private:
static constexpr char ArrayBegin = '[';
static constexpr char ArrayEnd = ']';
static constexpr char NameSeparator = ':';
static constexpr char ValueSeparator = ',';
static constexpr char ObjectBegin = '{';
static constexpr char ObjectEnd = '}';
static constexpr char Quote = '"';
private:
array_pointer get_array();
bool get_false();
bool get_true();
std::nullptr_t get_null();
object_pointer get_object();
std::pair<std::string, value> get_pair();
std::string get_number();
std::string get_string();
value get_value();
private:
char peek();
private:
template <class Tr>
std::string get_number(const Tr &);
std::string get_number(const std::random_access_iterator_tag &);
private:
const In begin_;
In cur_;
const In end_;
};
}
#endif
This diff is collapsed.
#ifndef VALUE_20110526_H_
#define VALUE_20110526_H_
namespace json {
class array;
class object;
namespace detail {
template <class T>
constexpr T static_max(T n) {
return n;
}
template <class T, class ... Args>
constexpr T static_max(T n, Args ... args) {
return n > static_max(args...) ? n : static_max(args...);
}
template <class... Types>
struct aligned_traits {
static constexpr std::size_t alignment_value = static_max(alignof(Types)...);
static constexpr std::size_t size_value = static_max(sizeof(Types)...);
};
}
class value {
friend bool is_string(const value &v);
friend bool is_bool(const value &v);
friend bool is_number(const value &v);
friend bool is_object(const value &v);
friend bool is_array(const value &v);
friend bool is_null(const value &v);
friend std::string to_string(const value &v);
friend bool to_bool(const value &v);
friend double to_number(const value &v);
friend object to_object(const value &v);
friend array to_array(const value &v);
friend const object &as_object(const value &v);
friend object &as_object(value &v);
friend const array &as_array(const value &v);
friend array &as_array(value &v);
friend const std::string &as_string(const value &v);
friend std::string &as_string(value &v);
friend bool has_key(const value &v, const std::string &key);
friend bool operator==(const value &lhs, const value &rhs);
friend bool operator!=(const value &lhs, const value &rhs);
template <class In>
friend class parser;
private:
struct numeric_t {};
// create a value from a numeric string, internal use only!
value(std::string s, const numeric_t &);
public:
// intialize from basic types
value(bool b);
value(const array &a);
value(const char *s);
value(const object &o);
value(std::string s);
template <class T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
value(T n);
value(const std::nullptr_t &);
public:
value();
~value();
public:
explicit value(object_pointer o);
explicit value(array_pointer a);
public:
value(const value &other);
value &operator=(const value &rhs);
public:
void swap(value &other);
public:
enum type {
type_invalid,
type_string,
type_number,
type_object,
type_array,
type_boolean,
type_null
};
public:
const value operator[](const std::string &key) const;
const value operator[](std::size_t n) const;
value &operator[](const std::string &key);
value &operator[](std::size_t n);
private:
const std::string &as_string() const;
std::string &as_string();
const object &as_object() const;
object &as_object();
const array &as_array() const;
array &as_array();
private:
struct invalid_t {};
// I would love to use std::aligned_union, but it doesn't seem widely supported
// so instead, we kinda make our own, first we need a type which has the correct
// size and alignment requirements based on the types we want to store
using Tr = detail::aligned_traits<invalid_t, object_pointer, array_pointer, std::string>;
struct storage_type {
alignas(Tr::alignment_value) uint8_t data[Tr::size_value];
};
storage_type value_;
type type_;
};
bool operator==(const value &lhs, const value &rhs);
bool operator!=(const value &lhs, const value &rhs);
}
#endif
#ifndef VALUE_20120424_TCC_
#define VALUE_20120424_TCC_
namespace json {
//------------------------------------------------------------------------------
// Name: ~value
//------------------------------------------------------------------------------
inline value::~value() {
using std::string;
switch(type_) {
case value::type_string:
case value::type_number:
case value::type_null:
case value::type_boolean:
reinterpret_cast<std::string *>(&value_)->~string();
break;
case value::type_array:
reinterpret_cast<array_pointer *>(&value_)->~array_pointer();
break;
case value::type_object:
reinterpret_cast<object_pointer *>(&value_)->~object_pointer();
break;
case value::type_invalid:
break;
}
}
//------------------------------------------------------------------------------
// Name: value
//------------------------------------------------------------------------------
inline value::value() : type_(type_invalid) {
}
//------------------------------------------------------------------------------
// Name: value
//------------------------------------------------------------------------------
inline value::value(const std::nullptr_t &): type_(type_null) {
new (&value_) std::string("null");
}
//------------------------------------------------------------------------------
// Name: value
//------------------------------------------------------------------------------
inline value::value(object_pointer o) : type_(type_object) {
new (&value_) object_pointer(std::move(o));
}
//------------------------------------------------------------------------------
// Name: value
//------------------------------------------------------------------------------
inline value::value(array_pointer a) : type_(type_array) {
new (&value_) array_pointer(std::move(a));
}
//------------------------------------------------------------------------------
// Name: value
//------------------------------------------------------------------------------
inline value::value(std::string s, const numeric_t &) : type_(type_number) {
new (&value_) std::string(std::move(s));
}
//------------------------------------------------------------------------------
// Name: value
//------------------------------------------------------------------------------
inline value::value(std::string s) : type_(type_string) {
new (&value_) std::string(std::move(s));
}
//------------------------------------------------------------------------------
// Name: value
//------------------------------------------------------------------------------
template <class T, typename>
value::value(T n) : type_(type_number) {
new (&value_) std::string(std::to_string(n));
}
//------------------------------------------------------------------------------
// Name: value
//------------------------------------------------------------------------------
inline value::value(const char *s) : type_(type_string) {
new (&value_) std::string(s);
}
//------------------------------------------------------------------------------
// Name: value
//------------------------------------------------------------------------------
inline value::value(bool b) : type_(type_boolean) {
new (&value_) std::string(b ? "true" : "false");
}
//------------------------------------------------------------------------------
// Name: value
//------------------------------------------------------------------------------
inline value::value(const value &other) : type_(other.type_) {
// copy from the other object
switch(type_) {
case value::type_string:
case value::type_number:
case value::type_null:
case value::type_boolean:
new (&value_) std::string(*reinterpret_cast<const std::string *>(&other.value_));
break;
case value::type_array:
new (&value_) array_pointer(*reinterpret_cast<const array_pointer *>(&other.value_));
break;
case value::type_object:
new (&value_) object_pointer(*reinterpret_cast<const object_pointer *>(&other.value_));
break;
case value::type_invalid:
break;
}
}
//------------------------------------------------------------------------------
// Name: operator=
//------------------------------------------------------------------------------
inline value &value::operator=(const value &rhs) {
if(this != &rhs) {
value(rhs).swap(*this);
}
return *this;
}
//------------------------------------------------------------------------------
// Name: swap
//------------------------------------------------------------------------------
inline void value::swap(value &other) {
using std::swap;
swap(value_, other.value_);
swap(type_, other.type_);
}
//------------------------------------------------------------------------------
// Name: operator[]
//------------------------------------------------------------------------------
inline const value value::operator[](const std::string &key) const {
return as_object()[key];
}
//------------------------------------------------------------------------------
// Name: operator[]
//------------------------------------------------------------------------------
inline const value value::operator[](std::size_t n) const {
return as_array()[n];
}
//------------------------------------------------------------------------------
// Name: operator[]
//------------------------------------------------------------------------------
inline value &value::operator[](const std::string &key) {
return as_object()[key];
}
//------------------------------------------------------------------------------
// Name: operator[]
//------------------------------------------------------------------------------
inline value &value::operator[](std::size_t n) {
return as_array()[n];
}
//------------------------------------------------------------------------------
// Name: value
//------------------------------------------------------------------------------
inline value::value(const array &a) : type_(type_array) {
new (&value_) array_pointer(std::make_shared<array>(a));
}
//------------------------------------------------------------------------------
// Name: value
//------------------------------------------------------------------------------
inline value::value(const object &o) : type_(type_object) {
new (&value_) object_pointer(std::make_shared<object>(o));
}
//------------------------------------------------------------------------------
// Name: operator==
//------------------------------------------------------------------------------
inline bool operator==(const value &lhs, const value &rhs) {
if(lhs.type_ == rhs.type_) {
switch(lhs.type_) {
case value::type_string:
return as_string(lhs) == as_string(rhs);
case value::type_number:
return to_number(lhs) == to_number(rhs);
case value::type_null:
return true;
case value::type_boolean:
return to_bool(lhs) == to_bool(rhs);
case value::type_array:
return as_array(lhs) == as_array(rhs);
case value::type_object:
return as_object(lhs) == as_object(rhs);
case value::type_invalid:
break;
}
}
return false;
}
//------------------------------------------------------------------------------
// Name: operator!=
//------------------------------------------------------------------------------
inline bool operator!=(const value &lhs, const value &rhs) {
return !(lhs == rhs);
}
//------------------------------------------------------------------------------
// Name: as_string
//------------------------------------------------------------------------------
inline const std::string &value::as_string() const {
switch(type_) {
case value::type_string:
case value::type_number:
case value::type_null:
case value::type_boolean:
return *reinterpret_cast<const std::string *>(&value_);
default:
throw invalid_type_cast();
}
}
//------------------------------------------------------------------------------
// Name: as_string
//------------------------------------------------------------------------------
inline std::string &value::as_string() {
switch(type_) {
case value::type_string:
case value::type_number:
case value::type_null:
case value::type_boolean:
return *reinterpret_cast<std::string *>(&value_);
default:
throw invalid_type_cast();
}
}
//------------------------------------------------------------------------------
// Name: as_object
//------------------------------------------------------------------------------
inline const object &value::as_object() const {
if(type_ != type_object) {
throw invalid_type_cast();
}
return **reinterpret_cast<const object_pointer *>(&value_);
}
//------------------------------------------------------------------------------
// Name: as_object
//------------------------------------------------------------------------------
inline object &value::as_object() {
if(type_ != type_object) {
throw invalid_type_cast();
}
return **reinterpret_cast<object_pointer *>(&value_);
}
//------------------------------------------------------------------------------
// Name: as_array
//------------------------------------------------------------------------------
inline const array &value::as_array() const {
if(type_ != type_array) {
throw invalid_type_cast();
}
return **reinterpret_cast<const array_pointer *>(&value_);
}
//------------------------------------------------------------------------------
// Name: as_array
//------------------------------------------------------------------------------
inline array &value::as_array() {
if(type_ != type_array) {
throw invalid_type_cast();
}
return **reinterpret_cast<array_pointer *>(&value_);
}
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment