diff --git a/.gitignore b/.gitignore index b97fd2f..6d3b93d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,39 +1,40 @@ -*.d -*.o -*.obj -*.out -*.a -*.res -*.lib -*.dll -*.exe -*.pyc -*.pyd -*.dat - -*.depend -*.layout -*.log -*.stackdump - -out* -*temp* - -data/data.cc -!data/pattern.dat - -*.dot -optimize/*.png -optimize/*/*.png - -single/*.cc - -!optimize/*.exe -!optimize/*/*.exe - -python/reversi.py -python/*wrap.* - -wxsmith/*.xrc - -doc/* \ No newline at end of file +*.d +*.o +*.obj +*.out +*.a +*.so +*.res +*.lib +*.dll +*.exe +*.pyc +*.pyd +*.dat + +*.depend +*.layout +*.log +*.stackdump + +*reversi + +out* +*temp* + +data/data.cc +!data/pattern.dat + +*.dot +profile/*.png + +*merge.cc + +python/reversi.py +python/*wrap.* +python/image/* + +doc/* + +build/* +!build/CMakeLists.txt diff --git a/Readme.md b/Readme.md index 00bd504..61ff4b8 100644 --- a/Readme.md +++ b/Readme.md @@ -1,84 +1,61 @@ -## Reversi - -### Screenshot -![](./image/reversi.png) - -### Overview -Reversi (also called Othello) is a kind of strategy board game which involves play by two parties on an eight-by-eight square grid. For details of reversi please go to [https://en.wikipedia.org/wiki/Reversi](https://en.wikipedia.org/wiki/Reversi). - -This reversi project is my simple work. The kernel is written in C++11 whith a bit inline assembly. Script language Python and TCL can be embeded to ease the interaction with users. The GUI is built with wxwidgets. It can be written in C++ or python. The sources of this project can be merged in to a single file and submitted to [Botzone](https://botzone.org) which is a online platform for competition of differnt bots made by students and other programming learners. - -### Build reversi - -- Prerequisites - - Essential - - A decent C++ compiler - C++11 must be supported by this version of compiler. The project will not use inline assembly when compiled by Visual Studio as MS compiler supports neither 64-bit inline assembly nor AT&T flavor syntax. - - Optional - - CodeBlocks or Cbp2make (if you want to utilize the .cbp codeblocks project file to build this project) - - TCL (if you want to embed tool command language) - - wxWidgets (required by the GUI version written in C++) - - python (required by the GUI version written in Python and some simple scripts) - - swig (required by the GUI version written in Python) - - wxPython (required by the GUI version written in Python) - -Personally, I've only built the project on 64-bit windows and cygwin but I believe it can migrate to other platforms. - -- Build reversi with only basic functions - 2. Create a C++ project. - 3. Add following files to your project. - type.h type.cc reversi.h reversi.cc flip.cc search.h search.cc pattern.h pattern.cc (game.h game.cc) - 4. Write your main.cc source file with "reversi.h" ("game.h") included. - 5. Compile it. - -- Build reversi which can be executed on [Botzone](https://botzone.org) - 1. Open reversi_json.cbp with CodeBlocks or use cbp2make.exe to generate makefile on your own platform. - 2. Compile it. - - To submit it to Botzone, several sources have to be merged into a single file. If you have python installed, run the script ./single/merge.py and main_merge.cc will be generated automatically. - -- Build reversi with tcl embeded - 1. Install TCL, Boost. Download cpptcl. - 2. Open reversi.cbp with CodeBlocks or use cbp2make.exe to generate makefile on your own platform. - 3. Change the paths of libraries. - 4. Compile it. - -- Build reversi GUI version with tcl embeded - 1. Install TCL, Boost, wxwidgets. Download cpptcl. - 2. Open reversi_gui.cbp with CodeBlocks or use cbp2make.exe to generate makefile on your own platform. - 3. Change the paths of libraries. - 4. Compile it. - -- Build reversi python GUI version (apparently there's no need to embed tcl anymore) - 1. Install python, swig, wxpython. - 2. Run cmd/shell. - 3. Enter the directory $(REVERSI_PROJECT)/python/ - 4. Type following command. - `swig -python -c++ -threads reversi.i` - `python setup.py build_ext --inplace --compiler=mingw32` - Note: `--compiler=mingw32` has to be changed according to your compiler. - If it's built successfully, dynamic link library _reversi.pyd or _reversi.dll or _reversi.so should be generated and main.py can be executed. - -### Development - - reversi.h: class board - │ board::flip() - │ board::score() - │ board::search() - │ ... - │ - └───game.h: class game - │ │ - │ └───reversi_tcl.h - │ │ │ - │ │ └───main.cc (C++ tcl console project) - │ │ │ - │ │ └───reversi_gui.h: class game_gui - │ │ │ - │ │ └───reversi_guiMain.h: class reversi_guiFrame (C++ tcl GUI project) - │ │ - │ └───reversi_gui.py: class game_gui - │ │ - │ └───main.py (python GUI project) - │ - └───main_json.cc (Botzone online project) +## Reversi + +### Screenshot +![](./image/reversi.png) + +### Overview +Reversi (also called Othello) is a kind of strategy board game which involves play by two parties on an eight-by-eight square grid. For details of reversi please go to [https://en.wikipedia.org/wiki/Reversi](https://en.wikipedia.org/wiki/Reversi). + +This reversi project is my simple work. The kernel is written in C++11 whith a bit inline assembly. The GUI is witten in python. The sources of this project can be merged in to a single file and submitted to [Botzone](https://botzone.org) which is a online platform for competition of differnt bots made by students and other programming learners. + +### Build + +- Prerequisites + - A decent C++ compiler + C++11 must be supported by this compiler. Inline assembly will not be used when compiled by Visual Studio as MS compiler supports neither 64-bit inline assembly nor AT&T flavor syntax. + - [Python3](https://www.python.org/) (required by the GUI written in Python and some simple scripts) + - [swig](http://swig.org/) (required by the GUI written in Python) + - [wxPython](https://www.wxpython.org/) (required by the GUI written in Python) + - [CMake](https://cmake.org/) + +- Build reversi with GUI + 1. Compile the source code and generate dynamic link library _reversi.so + `cd build` + `cmake .` (To generate MinGW Makefiles on windows, it should be `cmake -G"MinGW Makefiles" .`) + `make` + `cd ..` + 2. Execute the project + `cd python` + `python3 main.py` + +- Build reversi for [Botzone](https://botzone.org) + 1. Enter the directory botzone/ + `cd botzone` + 2. Merge sources into a single file "main_merge.cc" + `python3 merge.py` + +### Development + +- File Structure + + cpp/reversi.h: class board + │ cpp/flip.cc board::flip() + │ cpp/reversi.cc + │ cpp/search.cc board::search() + │ ... + │ + └───python/game.py: class game + │ │ + │ └───python/main.py (python GUI project) + │ + └───botzone/main.cc (Botzone online project) + +- Profile (only available on UNIX-like systems) + - Prerequisites + - [graphiz](https://www.graphviz.org/) + - [gprof2dot](https://github.com/jrfonseca/gprof2dot) + + 1. Enter the directory profile/ + `cd profile` + 2. Compile the source code and generate files "prof.log" "test.png" + `make` diff --git a/asm.h b/asm.h deleted file mode 100644 index a2155b7..0000000 --- a/asm.h +++ /dev/null @@ -1,56 +0,0 @@ -/** @file asm.h - * @brief This file includes some macros for inline assembly. - */ - -#ifndef ASM_H -#define ASM_H - -#define asm_rol(brd,val) \ - asm volatile( \ - "rol %1, %0;" \ - : "+r"(brd) \ - : "c"(char(val)) \ - ) - -#define asm_ror(brd,val) \ - asm volatile( \ - "ror %1, %0;" \ - : "+r"(brd) \ - : "c"(char(val)) \ - ) - -#define asm_bswap(brd) \ - asm volatile( \ - "bswap %0;" \ - : "+r"(brd) \ - ) - -#define asm_popcnt(brd,result) \ - asm volatile( \ - "popcnt %1, %0;" \ - : "=r"(result) \ - : "r"(brd) \ - ) - -#define asm_tzcnt(brd,result) \ - asm volatile( \ - "tzcnt %1, %0;" \ - :"=r"(result) \ - :"r"(brd) \ - ) - -#define asm_pext(brd, mask, result) \ - asm volatile( \ - "pext %1, %2, %0;" \ - : "=r"(result) \ - : "r"(mask), "r"(brd) \ - ) - -#define asm_pdep(brd, mask, result) \ - asm volatile( \ - "pdep %1, %2, %0;" \ - : "=r"(result) \ - : "r"(mask), "r"(brd) \ - ) - -#endif //ASM_H \ No newline at end of file diff --git a/bot/data b/bot/data new file mode 120000 index 0000000..4909e06 --- /dev/null +++ b/bot/data @@ -0,0 +1 @@ +../data \ No newline at end of file diff --git a/single/compress.py b/botzone/compress.py similarity index 96% rename from single/compress.py rename to botzone/compress.py index c476c2e..3533707 100644 --- a/single/compress.py +++ b/botzone/compress.py @@ -1,68 +1,68 @@ -import re; -import os; -import codecs - -filename = "main_merge.cc"; - -fobj = codecs.open(filename,"r","utf-8"); -lines = fobj.readlines(); -fobj.close(); - -lines = "".join(lines); - -# suppress single line comments -lines = re.sub(r"(.*)//.*\n","\g<1>\n",lines); -# suppress multi-line comments -lines = re.sub(r"\/\*[^\/]*\*\/","",lines); -# suppress newline -lines = re.sub(r"\\\s*\n","",lines); - -# suppress blank -lines = re.sub(r"\s*\n\s*","\n",lines); -lines = re.sub(r"(?<=\n)(?!\s*#)([^\n]*)\n(?!\s*#)","\g<1>",lines); - -lines_buff = []; -while True: - piece = re.search(r"[^\"']*(?:[\"'])",lines); - if piece == None: - break; - piece = piece.span(); - lines_buff += [lines[piece[0]:piece[1]]]; - lines = lines[piece[1]:]; -lines = lines_buff + [lines]; - -for i in range(len(lines)): - if (i & 1) == 0: - lines[i] = re.sub(r"(?:\B(?:(?!\n)\s)+\B|\b(?:(?!\n)\s)+\B|\B(?:(?!\n)\s)+\b)","",lines[i]); -lines = "".join(lines); - -# replace variable names -lines = re.sub(r"\bboard\b","b",lines); -lines = re.sub(r"\bcolor\b","cl",lines); -lines = re.sub(r"\bchoice\b","ch",lines); -lines = re.sub(r"\bcoordinate\b","co",lines); -lines = re.sub(r"\bchessman\b","cm",lines); -lines = re.sub(r"\bgame\b","g",lines); -lines = re.sub(r"\bpattern\b","pn",lines); -lines = re.sub(r"\bbrd_blue\b","b_b",lines); -lines = re.sub(r"\bbrd_green\b","b_g",lines); -lines = re.sub(r"\bbrd_white\b","b_w",lines); -lines = re.sub(r"\bbrd_black\b","b_bl",lines); -lines = re.sub(r"\bbrd_type\b","b_t",lines); -lines = re.sub(r"\bcbrd_type\b","cb_t",lines); -lines = re.sub(r"\bpos_type\b","p_t",lines); -lines = re.sub(r"\bcpos_type\b","cp_t",lines) -lines = re.sub(r"\bcalc_type\b","c_t",lines); -lines = re.sub(r"\bccalc_type\b","cc_t",lines); -lines = re.sub(r"\bheight\b","h",lines); -lines = re.sub(r"\balpha\b","A",lines); -lines = re.sub(r"\bbeta\b","B",lines); -lines = re.sub(r"\bgamma\b","G",lines); -lines = re.sub(r"\bmask\b","m",lines); -lines = re.sub(r"\temp\b","t",lines); - -filename = "main_compress.cc"; - -fobj = codecs.open(filename,"w"); -fobj.writelines(lines); +import re; +import os; +import codecs + +filename = "main_merge.cc"; + +fobj = codecs.open(filename,"r","utf-8"); +lines = fobj.readlines(); +fobj.close(); + +lines = "".join(lines); + +# suppress single line comments +lines = re.sub(r"(.*)//.*\n","\g<1>\n",lines); +# suppress multi-line comments +lines = re.sub(r"\/\*[^\/]*\*\/","",lines); +# suppress newline +lines = re.sub(r"\\\s*\n","",lines); + +# suppress blank +lines = re.sub(r"\s*\n\s*","\n",lines); +lines = re.sub(r"(?<=\n)(?!\s*#)([^\n]*)\n(?!\s*#)","\g<1>",lines); + +lines_buff = []; +while True: + piece = re.search(r"[^\"']*(?:[\"'])",lines); + if piece == None: + break; + piece = piece.span(); + lines_buff += [lines[piece[0]:piece[1]]]; + lines = lines[piece[1]:]; +lines = lines_buff + [lines]; + +for i in range(len(lines)): + if (i & 1) == 0: + lines[i] = re.sub(r"(?:\B(?:(?!\n)\s)+\B|\b(?:(?!\n)\s)+\B|\B(?:(?!\n)\s)+\b)","",lines[i]); +lines = "".join(lines); + +# replace variable names +lines = re.sub(r"\bboard\b","b",lines); +lines = re.sub(r"\bcolor\b","cl",lines); +lines = re.sub(r"\bchoice\b","ch",lines); +lines = re.sub(r"\bcoordinate\b","co",lines); +lines = re.sub(r"\bchessman\b","cm",lines); +lines = re.sub(r"\bgame\b","g",lines); +lines = re.sub(r"\bpattern\b","pn",lines); +lines = re.sub(r"\bbrd_blue\b","b_b",lines); +lines = re.sub(r"\bbrd_green\b","b_g",lines); +lines = re.sub(r"\bbrd_white\b","b_w",lines); +lines = re.sub(r"\bbrd_black\b","b_bl",lines); +lines = re.sub(r"\bbrd_type\b","b_t",lines); +lines = re.sub(r"\bcbrd_type\b","cb_t",lines); +lines = re.sub(r"\bpos_type\b","p_t",lines); +lines = re.sub(r"\bcpos_type\b","cp_t",lines) +lines = re.sub(r"\bcalc_type\b","c_t",lines); +lines = re.sub(r"\bccalc_type\b","cc_t",lines); +lines = re.sub(r"\bheight\b","h",lines); +lines = re.sub(r"\balpha\b","A",lines); +lines = re.sub(r"\bbeta\b","B",lines); +lines = re.sub(r"\bgamma\b","G",lines); +lines = re.sub(r"\bmask\b","m",lines); +lines = re.sub(r"\temp\b","t",lines); + +filename = "main_compress.cc"; + +fobj = codecs.open(filename,"w"); +fobj.writelines(lines); fobj.close(); \ No newline at end of file diff --git a/botzone/data b/botzone/data new file mode 120000 index 0000000..4909e06 --- /dev/null +++ b/botzone/data @@ -0,0 +1 @@ +../data \ No newline at end of file diff --git a/botzone/jsoncpp b/botzone/jsoncpp new file mode 120000 index 0000000..fa99cd4 --- /dev/null +++ b/botzone/jsoncpp @@ -0,0 +1 @@ +../cpp/jsoncpp \ No newline at end of file diff --git a/main_json.cc b/botzone/main.cc similarity index 79% rename from main_json.cc rename to botzone/main.cc index f4b75a2..0621857 100644 --- a/main_json.cc +++ b/botzone/main.cc @@ -5,8 +5,8 @@ #include "jsoncpp/json.h" -#include "reversi.h" -#include "pattern.h" +#include "../cpp/reversi.h" +#include "../cpp/pattern.h" using namespace std; @@ -54,7 +54,12 @@ int main(int argc, char *argv[], char *envp[]){ grp.load("./data/pattern2.dat"); - auto coord = brd.play(mthd_default,mycolor,-2); + method mthd = method(mthd_ab | mthd_pvs | mthd_kill | mthd_mtdf | mthd_ptn | mthd_trans); + short depth = -2; + auto p_mthd = brd.process_method(mthd, depth); + mthd = p_mthd.first; + depth = p_mthd.second; + auto coord = brd.play(mthd, mycolor, depth); // 决策结束,输出结果(你只需修改以上部分) diff --git a/botzone/makefile b/botzone/makefile new file mode 100644 index 0000000..b4c1d40 --- /dev/null +++ b/botzone/makefile @@ -0,0 +1,55 @@ +WORKDIR = `pwd` + +CC = gcc +CXX = g++ +AR = ar +LD = g++ +WINDRES = windres +RM = rm -f + +INC = +CFLAGS = +CXXFLAGS = -Wall -std=c++11 -O2 +RESINC = +LIBDIR = +LIB = +LDFLAGS = + +SRCDIR = ../cpp/ +OBJDIR = obj/ +OUTDIR = ./ + +SRC = $(wildcard $(SRCDIR)*.cc) main.cc +OBJ = $(patsubst %.cc, %.o, $(patsubst $(SRCDIR)%, $(OBJDIR)%, $(SRC))) +OUT = $(OUTDIR)reversi + +.PHONY: all clean before + +all: $(OUT) + +clean: + -$(RM) $(OBJDIR)*.o + -$(RM) $(addprefix $(OUTDIR), *.o *.exe *.dll *.so *.pyd *.log *.out) $(OUT) + +before: + test -d $(OBJDIR) || mkdir -p $(OBJDIR) + test -d $(OUTDIR) || mkdir -p $(OUTDIR) + +$(OUT): before $(OBJ) + $(LD) $(LDFLAGS) $(LIBDIR) $(OBJ) -o $@ + +$(OBJDIR)reversi.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM $(SRCDIR)reversi.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(OBJDIR)flip.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM $(SRCDIR)flip.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(OBJDIR)search.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM $(SRCDIR)search.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(OBJDIR)pattern.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM $(SRCDIR)pattern.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +main.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM main.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ + diff --git a/single/merge.py b/botzone/merge.py similarity index 50% rename from single/merge.py rename to botzone/merge.py index 0571ffe..be8272a 100644 --- a/single/merge.py +++ b/botzone/merge.py @@ -1,32 +1,28 @@ -import re; -import os; -import codecs - -src_dir = "../"; -# src = ["type.h","reversi.h","game.h","pattern.h","tree.h", - # "type.cc","reversi.cc","flip.cc","search.cc","pattern.cc","tree.cc"]; -# src = [src_dir + x for x in src]; -# src += ["main.cc"]; - -src = ["type.h","asm.h","reversi.h","search.h","game.h","matrix.h","pattern.h","tree.h", - "type.cc","reversi.cc","flip.cc","search.cc","pattern.cc","tree.cc","main_json.cc"]; -src = [src_dir + x for x in src]; - -lines = []; -for filename in src: - assert(os.path.isfile(filename)) - fobj = codecs.open(filename,"r","utf-8"); - lines += fobj.readlines(); - lines[-1] += "\n"; - fobj.close(); - -lines = "".join(lines); - -# suppress redundant include header macros -lines = re.sub(r"\s*#include *\"(?!json).*\".*\n","\n",lines); - -target = "main_merge.cc" - -fobj = codecs.open(target,"w","utf-8"); -fobj.writelines(lines); -fobj.close(); \ No newline at end of file +import re; +import os; +import codecs + +src_dir = "../cpp/"; + +src = ["type.h","asm.h","reversi.h", "hash.h","matrix.h","pattern.h", + "reversi.cc","flip.cc","search.cc","pattern.cc"]; +src = [src_dir + x for x in src] + ["main.cc"]; + +lines = []; +for filename in src: + assert(os.path.isfile(filename)) + fobj = codecs.open(filename,"r","utf-8"); + lines += fobj.readlines(); + lines[-1] += "\n"; + fobj.close(); + +lines = "".join(lines); + +# suppress redundant include header macros +lines = re.sub(r"\s*#include *\"(?!json).*\".*\n","\n",lines); + +target = "main_merge.cc" + +fobj = codecs.open(target,"w","utf-8"); +fobj.writelines(lines); +fobj.close(); diff --git a/botzone/parse.awk b/botzone/parse.awk new file mode 100644 index 0000000..19881cf --- /dev/null +++ b/botzone/parse.awk @@ -0,0 +1,9 @@ +BEGIN {} +{ + for (i = 1; i <= NF; ++i) { + if($i != "\\"){ + printf "%s ", $i + } + } +} +END {printf "\n"} diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt new file mode 100644 index 0000000..5a7053e --- /dev/null +++ b/build/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required (VERSION 2.6) +project (reversi) +set (REVERSI_VERSION 2.1) + +include (CheckCXXCompilerFlag) +CHECK_CXX_COMPILER_FLAG ("-std=c++11" COMPILER_SUPPORTS_CXX11) +if (NOT COMPILER_SUPPORTS_CXX11) + message(FATAL_ERROR "Compiler ${CMAKE_CXX_COMPILER} has no C++11 support.") +endif () + +include (FindPythonLibs) + +set (cpp_dir "${PROJECT_SOURCE_DIR}/../cpp") +set (python_dir "${PROJECT_SOURCE_DIR}/../python") +if (WIN32) + if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set (CMAKE_CXX_FLAGS "-Wall -D_hypot=hypot -DMS_WIN64") + else () + set (CMAKE_CXX_FLAGS "-Wall -D_hypot=hypot -DMS_WIN32") + endif () +else () + set (CMAKE_CXX_FLAGS "-Wall") +endif () +set (CMAKE_CXX_FLAGS_DEBUG "-Og -g -DEBUG") +set (CMAKE_CXX_FLAGS_RELEASE "-O3 -NDEBUG") +set (CMAKE_SHARED_LIBRARY_PREFIX "") + +include_directories ("${PYTHON_INCLUDE_DIRS}") + +set ( + head_file + ${cpp_dir}/type.h + ${cpp_dir}/asm.h + ${cpp_dir}/reversi.h + ${cpp_dir}/hash.h + ${cpp_dir}/log.h + ${cpp_dir}/matrix.h + ${cpp_dir}/pattern.h +) + +set ( + source_file + ${cpp_dir}/reversi.cc + ${cpp_dir}/flip.cc + ${cpp_dir}/pattern.cc + ${cpp_dir}/search.cc + ${python_dir}/reversi_wrap.cxx +) + +add_custom_command ( + OUTPUT ${python_dir}/reversi_wrap.cxx + COMMAND swig -python -c++ -threads -o ${python_dir}/reversi_wrap.cxx ${python_dir}/reversi.i + DEPENDS ${python_dir}/reversi.i ${head_file} +) + +add_library(_reversi SHARED ${source_file}) +set_property(TARGET _reversi PROPERTY CXX_STANDARD 11) +set_property(TARGET _reversi PROPERTY CXX_STANDARD_REQUIRED ON) +target_link_libraries (_reversi ${PYTHON_LIBRARIES}) + +if (WIN32) + add_custom_command(TARGET _reversi POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ ${python_dir}/_reversi.pyd + ) +else () + add_custom_command(TARGET _reversi POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ ${python_dir}/ + ) +endif () diff --git a/cpp/asm.h b/cpp/asm.h new file mode 100644 index 0000000..86a667d --- /dev/null +++ b/cpp/asm.h @@ -0,0 +1,204 @@ +/** @file asm.h + * @brief This file includes some macros for inline assembly. + */ + +#ifndef ASM_H +#define ASM_H + +#include "type.h" + +#define asm_bt(brd, pos, result) \ + asm volatile( \ + "bt %2,%1;" \ + "setc %0;" \ + :"=&r"(result) \ + :"r"(brd), "r"(pos) \ + ) + +#define equ_bt(brd, pos, result) \ + (result = bool(brd & (1 << pos))) + +#ifdef USE_ASM + #define fun_bt(brd, mask, result) asm_bt(brd, mask, result) +#else + #define fun_bt(brd, mask, result) equ_bt(brd, mask, result) +#endif //USE_ASM + +#define asm_bts(brd, pos) \ + asm volatile( \ + "bts %1,%0;" \ + :"+r"(brd) \ + :"r"(pos) \ + ) + +#define equ_bts(brd, pos) \ + (brd |= 1 << pos) + +#ifdef USE_ASM + #define fun_bts(brd, pos) asm_bts(brd, pos) +#else + #define fun_bts(brd, pos) equ_bts(brd, pos) +#endif //USE_ASM + +#define asm_btr(brd, pos) \ + asm volatile( \ + "btr %1,%0;" \ + :"+r"(brd) \ + :"r"(pos) \ + ) + +#define equ_btr(brd, pos) \ + (brd &= ~(1 << pos)) + +#ifdef USE_ASM + #define fun_btr(brd, pos) asm_btr(brd, pos) +#else + #define fun_btr(brd, pos) equ_btr(brd, pos) +#endif //USE_ASM + +#define asm_rol(brd, val) \ + asm volatile( \ + "rol %1, %0;" \ + : "+r"(brd) \ + : "c"(char(val)) \ + ) + +inline void equ_rol(unsigned char& brd, char val){ + brd = (brd << val) | (brd >> (8 - val)); +} +inline void equ_rol(ull& brd, char val){ + brd = (brd << val) | (brd >> (64 - val)); +} + +#ifdef USE_ASM + #define fun_rol(brd, val) asm_rol(brd, val) +#else + #define fun_rol(brd, val) equ_rol(brd, val) +#endif //USE_ASM + +#define asm_ror(brd, val) \ + asm volatile( \ + "ror %1, %0;" \ + : "+r"(brd) \ + : "c"(char(val)) \ + ) + +inline void equ_ror(unsigned char& brd, char val){ + brd = (brd >> val) | (brd << (8 - val)); +} +inline void equ_ror(ull& brd, char val){ + brd = (brd >> val) | (brd << (64 - val)); +} + +#ifdef USE_ASM + #define fun_ror(brd, val) asm_ror(brd, val) +#else + #define fun_ror(brd, val) equ_ror(brd, val) +#endif //USE_ASM + +#define asm_bswap(brd) \ + asm volatile( \ + "bswap %0;" \ + : "+r"(brd) \ + ) + +inline void equ_bswap(ull& brd){ + brd = (brd & 0xff00ff00ff00ff00) >> 8 | (brd & 0x00ff00ff00ff00ff) << 8; + brd = (brd & 0xffff0000ffff0000) >> 16 | (brd & 0x0000ffff0000ffff) << 16; + brd = (brd & 0xffffffff00000000) >> 32 | (brd & 0x00000000ffffffff) << 32; +} + +#ifdef USE_ASM + #define fun_bswap(brd) asm_bswap(brd); +#else + #define fun_bswap(brd) equ_bswap(brd); +#endif //USE_ASM + +#define asm_popcnt(brd, result) \ + asm volatile( \ + "popcnt %1, %0;" \ + : "=r"(result) \ + : "r"(brd) \ + ) + +inline void equ_popcnt(cull brd, ull& result){ + result = brd - ((brd >> 1) & 0x5555555555555555); + result = (result & 0x3333333333333333) + ((result >> 2) & 0x3333333333333333); + result = (result + (result >> 4)) & 0x0F0F0F0F0F0F0F0F; + result = (result * 0x0101010101010101) >> 56; +} + +#ifdef USE_ASM + #define fun_popcnt(brd, result) asm_popcnt(brd, result) +#else + #define fun_popcnt(brd, result) equ_popcnt(brd, result) +#endif //USE_ASM + +#define asm_tzcnt(brd, result) \ + asm volatile( \ + "tzcnt %1, %0;" \ + :"=r"(result) \ + :"r"(brd) \ + ) + +inline void equ_tzcnt(cull brd, ull& result){ + fun_popcnt(~brd & (brd - 1), result); +} + +#ifdef USE_ASM + #define fun_tzcnt(brd, result) asm_tzcnt(brd, result) +#else + #define fun_tzcnt(brd, result) equ_tzcnt(brd, result) +#endif //USE_ASM + +#define asm_pext(brd, mask, result) \ + asm volatile( \ + "pext %1, %2, %0;" \ + : "=r"(result) \ + : "r"(mask), "r"(brd) \ + ) + +inline void equ_pext(cull brd, cull mask, ull& result){ + ull msk; + result = 0; + msk = mask; + for(ull i = 1; msk; i <<= 1){ + if(brd & msk & -msk){ + result |= i; + } + msk &= msk - 1; + } +} + +#ifdef USE_ASM_BMI2 + #define fun_pext(brd, mask, result) asm_pext(brd, mask, result) +#else + #define fun_pext(brd, mask, result) equ_pext(brd, mask, result) +#endif //USE_ASM_BMI2 + +#define asm_pdep(brd, mask, result) \ + asm volatile( \ + "pdep %1, %2, %0;" \ + : "=r"(result) \ + : "r"(mask), "r"(brd) \ + ) + +inline void equ_pdep(cull brd, cull mask, ull& result){ + ull msk; + result = 0; + msk = mask; + for(ull i = 1; msk; i <<= 1){ + if(brd & i){ + result |= msk & -msk; + } + msk &= msk - 1; + } +} + +#ifdef USE_ASM_BMI2 + #define fun_pdep(brd, mask, result) asm_pdep(brd, mask, result) +#else + #define fun_pdep(brd, mask, result) equ_pdep(brd, mask, result) +#endif //USE_ASM_BMI2 + +#endif //ASM_H diff --git a/flip.cc b/cpp/flip.cc similarity index 86% rename from flip.cc rename to cpp/flip.cc index 564d991..4ee5010 100644 --- a/flip.cc +++ b/cpp/flip.cc @@ -24,7 +24,7 @@ const pos_type pos_diag2[board::size2] = { 0,1,2,3,4,5,6,7 }; -const brd_type mask_h[board::size] = { +const ull mask_h[board::size] = { 0x00000000000000ff, 0x000000000000ff00, 0x0000000000ff0000, @@ -35,7 +35,7 @@ const brd_type mask_h[board::size] = { 0xff00000000000000 }; -const brd_type mask_v[board::size] = { +const ull mask_v[board::size] = { 0x0101010101010101, 0x0202020202020202, 0x0404040404040404, @@ -46,7 +46,7 @@ const brd_type mask_v[board::size] = { 0x8080808080808080 }; -const brd_type mask_d1[board::size * 2 - 1] = { +const ull mask_d1[board::size * 2 - 1] = { 0x0000000000000001, 0x0000000000000102, 0x0000000000010204, @@ -64,7 +64,7 @@ const brd_type mask_d1[board::size * 2 - 1] = { 0x8000000000000000 }; -const brd_type mask_d2[board::size * 2 - 1] = { +const ull mask_d2[board::size * 2 - 1] = { 0x0000000000000080, 0x0000000000008040, 0x0000000000804020, @@ -85,22 +85,22 @@ const brd_type mask_d2[board::size * 2 - 1] = { unsigned short table_flip[1 << 19]; struct flip_info{ - brd_type index_h, mask_h; - brd_type index_v, mask_v; - brd_type index_d1, mask_d1; - brd_type index_d2, mask_d2; - brd_type mask_hvd; + ull index_h, mask_h; + ull index_v, mask_v; + ull index_d1, mask_d1; + ull index_d2, mask_d2; + ull mask_hvd; }; flip_info table_flip_info[board::size2]; void board::flip(cbool color,cpos_type pos){ - brd_type& brd_blue = this->bget(color); - brd_type& brd_green = this->bget(!color); + ull& brd_blue = this->bget(color); + ull& brd_green = this->bget(!color); - brd_type piece, temp, mask, brd_result; - brd_type sum_blue = 0, sum_green = 0; + ull piece, temp, mask, brd_result; + ull sum_blue = 0, sum_green = 0; const flip_info& info = table_flip_info[pos]; //horizontal @@ -164,14 +164,14 @@ void board::flip(cbool color,cpos_type pos){ brd_green = (brd_green & ~mask) | (sum_green & mask); } -unsigned short flip_line(cbrd_type data){ +unsigned short flip_line(cull data){ unsigned short brd_blue = (data >> 8) & 0xff; unsigned short brd_blue_save = brd_blue; unsigned short brd_green = data & 0xff; unsigned short mask = 1 << (data >> 16); unsigned short result = 0; - brd_type pos = mask; + ull pos = mask; if((brd_blue | brd_green) & mask){ goto label_end; @@ -234,7 +234,7 @@ void board::config_flip(){ info.mask_hvd = info.mask_h | info.mask_v | info.mask_d1 | info.mask_d2; } - for(brd_type i = 0;i != (1 << 19);++i){ + for(ull i = 0;i != (1 << 19);++i){ if((i >> 8) & i & 0xff){}else{ table_flip[i] = flip_line(i); } @@ -286,13 +286,13 @@ void board::config_flip(){ #define flip_part_dr flip_part(drbound,dright,uleft) #define flip_fun(name,kernel) \ -\ + \ void name(board* const& ptr,cbool color,cpos_type _pos){ \ - brd_type& blue = ptr->bget(color), blue_save = blue; \ - brd_type& green = ptr->bget(!color); \ - brd_type mask = brd_type(1) << _pos;\ + ull& blue = ptr->bget(color), blue_save = blue; \ + ull& green = ptr->bget(!color); \ + ull mask = ull(1) << _pos;\ \ - brd_type pos = mask; \ + ull pos = mask; \ \ kernel \ \ diff --git a/cpp/hash.h b/cpp/hash.h new file mode 100644 index 0000000..a51f34f --- /dev/null +++ b/cpp/hash.h @@ -0,0 +1,66 @@ +#ifndef HASH_H +#define HASH_H + +#include +#include + +#include "type.h" +#include "reversi.h" + +struct slot; +class bucket; +typedef const slot& cslot; +typedef const bucket& cbucket; + +struct slot{ + board brd; + val_type alpha; + val_type beta; + short depth; + short pos; + + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + #endif + + void save(cslot slt){ + if(slt.brd != brd || slt.depth > depth){ + *this = slt; + }else if(slt.depth == depth){ + alpha = max(alpha, slt.alpha); + beta = min(beta, slt.beta); + pos = slt.pos; + } + } + + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif + +}; + +class bucket{ +public: + static const ull size = 1 << 20; + static const ull mask = size - 1; + +protected: + slot table[size]; + +public: + void clear(){ + memset(table, 0, sizeof(table)); + } + + slot& probe(cull key){ + return table[key & mask]; + } + + void save(cslot slt, cull key){ + slot& slt_old = table[key & mask]; + slt_old.save(slt); + } +}; + +#endif //HASH_H diff --git a/jsoncpp.cpp b/cpp/jsoncpp.cpp similarity index 96% rename from jsoncpp.cpp rename to cpp/jsoncpp.cpp index 260f19f..f4c0b15 100644 --- a/jsoncpp.cpp +++ b/cpp/jsoncpp.cpp @@ -1,3686 +1,3686 @@ -/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/). -/// It is intented to be used with #include - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is -released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur - -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. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - - -#include "jsoncpp/json.h" - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_tool.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED -#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED - -/* This header provides common string manipulation support, such as UTF-8, - * portable conversion from/to string... - * - * It is an internal header that must not be exposed. - */ - -namespace Json { - -/// Converts a unicode code-point to UTF-8. -static inline std::string codePointToUTF8(unsigned int cp) { - std::string result; - - // based on description from http://en.wikipedia.org/wiki/UTF-8 - - if (cp <= 0x7f) { - result.resize(1); - result[0] = static_cast(cp); - } else if (cp <= 0x7FF) { - result.resize(2); - result[1] = static_cast(0x80 | (0x3f & cp)); - result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); - } else if (cp <= 0xFFFF) { - result.resize(3); - result[2] = static_cast(0x80 | (0x3f & cp)); - result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); - result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); - } else if (cp <= 0x10FFFF) { - result.resize(4); - result[3] = static_cast(0x80 | (0x3f & cp)); - result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); - result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); - result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); - } - - return result; -} - -/// Returns true if ch is a control character (in range [0,32[). -static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } - -enum { - /// Constant that specify the size of the buffer that must be passed to - /// uintToString. - uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 -}; - -// Defines a char buffer for use with uintToString(). -typedef char UIntToStringBuffer[uintToStringBufferSize]; - -/** Converts an unsigned integer to string. - * @param value Unsigned interger to convert to string - * @param current Input/Output string buffer. - * Must have at least uintToStringBufferSize chars free. - */ -static inline void uintToString(LargestUInt value, char*& current) { - *--current = 0; - do { - *--current = char(value % 10) + '0'; - value /= 10; - } while (value != 0); -} - -/** Change ',' to '.' everywhere in buffer. - * - * We had a sophisticated way, but it did not work in WinCE. - * @see https://github.com/open-source-parsers/jsoncpp/pull/9 - */ -static inline void fixNumericLocale(char* begin, char* end) { - while (begin < end) { - if (*begin == ',') { - *begin = '.'; - } - ++begin; - } -} - -} // namespace Json { - -#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_tool.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_reader.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2011 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include "json_tool.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below -#define snprintf _snprintf -#endif - -#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 -// Disable warning about strdup being deprecated. -#pragma warning(disable : 4996) -#endif - -namespace Json { - -// Implementation of class Features -// //////////////////////////////// - -Features::Features() - : allowComments_(true), strictRoot_(false), - allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} - -Features Features::all() { return Features(); } - -Features Features::strictMode() { - Features features; - features.allowComments_ = false; - features.strictRoot_ = true; - features.allowDroppedNullPlaceholders_ = false; - features.allowNumericKeys_ = false; - return features; -} - -// Implementation of class Reader -// //////////////////////////////// - -static inline bool in(Reader::Char c, - Reader::Char c1, - Reader::Char c2, - Reader::Char c3, - Reader::Char c4) { - return c == c1 || c == c2 || c == c3 || c == c4; -} - -static inline bool in(Reader::Char c, - Reader::Char c1, - Reader::Char c2, - Reader::Char c3, - Reader::Char c4, - Reader::Char c5) { - return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; -} - -static bool containsNewLine(Reader::Location begin, Reader::Location end) { - for (; begin < end; ++begin) - if (*begin == '\n' || *begin == '\r') - return true; - return false; -} - -// Class Reader -// ////////////////////////////////////////////////////////////////// - -Reader::Reader() - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), features_(Features::all()), - collectComments_() {} - -Reader::Reader(const Features& features) - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), features_(features), collectComments_() { -} - -bool -Reader::parse(const std::string& document, Value& root, bool collectComments) { - document_ = document; - const char* begin = document_.c_str(); - const char* end = begin + document_.length(); - return parse(begin, end, root, collectComments); -} - -bool Reader::parse(std::istream& sin, Value& root, bool collectComments) { - // std::istream_iterator begin(sin); - // std::istream_iterator end; - // Those would allow streamed input from a file, if parse() were a - // template function. - - // Since std::string is reference-counted, this at least does not - // create an extra copy. - std::string doc; - std::getline(sin, doc, (char)EOF); - return parse(doc, root, collectComments); -} - -bool Reader::parse(const char* beginDoc, - const char* endDoc, - Value& root, - bool collectComments) { - if (!features_.allowComments_) { - collectComments = false; - } - - begin_ = beginDoc; - end_ = endDoc; - collectComments_ = collectComments; - current_ = begin_; - lastValueEnd_ = 0; - lastValue_ = 0; - commentsBefore_ = ""; - errors_.clear(); - while (!nodes_.empty()) - nodes_.pop(); - nodes_.push(&root); - - bool successful = readValue(); - Token token; - skipCommentTokens(token); - if (collectComments_ && !commentsBefore_.empty()) - root.setComment(commentsBefore_, commentAfter); - if (features_.strictRoot_) { - if (!root.isArray() && !root.isObject()) { - // Set error location to start of doc, ideally should be first token found - // in doc - token.type_ = tokenError; - token.start_ = beginDoc; - token.end_ = endDoc; - addError( - "A valid JSON document must be either an array or an object value.", - token); - return false; - } - } - return successful; -} - -bool Reader::readValue() { - Token token; - skipCommentTokens(token); - bool successful = true; - - if (collectComments_ && !commentsBefore_.empty()) { - // Remove newline characters at the end of the comments - size_t lastNonNewline = commentsBefore_.find_last_not_of("\r\n"); - if (lastNonNewline != std::string::npos) { - commentsBefore_.erase(lastNonNewline + 1); - } else { - commentsBefore_.clear(); - } - - currentValue().setComment(commentsBefore_, commentBefore); - commentsBefore_ = ""; - } - - switch (token.type_) { - case tokenObjectBegin: - successful = readObject(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenArrayBegin: - successful = readArray(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenNumber: - successful = decodeNumber(token); - break; - case tokenString: - successful = decodeString(token); - break; - case tokenTrue: - currentValue() = true; - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - break; - case tokenFalse: - currentValue() = false; - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - break; - case tokenNull: - currentValue() = Value(); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - break; - case tokenArraySeparator: - if (features_.allowDroppedNullPlaceholders_) { - // "Un-read" the current token and mark the current value as a null - // token. - current_--; - currentValue() = Value(); - currentValue().setOffsetStart(current_ - begin_ - 1); - currentValue().setOffsetLimit(current_ - begin_); - break; - } - // Else, fall through... - default: - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return addError("Syntax error: value, object or array expected.", token); - } - - if (collectComments_) { - lastValueEnd_ = current_; - lastValue_ = ¤tValue(); - } - - return successful; -} - -void Reader::skipCommentTokens(Token& token) { - if (features_.allowComments_) { - do { - readToken(token); - } while (token.type_ == tokenComment); - } else { - readToken(token); - } -} - -bool Reader::expectToken(TokenType type, Token& token, const char* message) { - readToken(token); - if (token.type_ != type) - return addError(message, token); - return true; -} - -bool Reader::readToken(Token& token) { - skipSpaces(); - token.start_ = current_; - Char c = getNextChar(); - bool ok = true; - switch (c) { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = readString(); - break; - case '/': - token.type_ = tokenComment; - ok = readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - token.type_ = tokenNumber; - readNumber(); - break; - case 't': - token.type_ = tokenTrue; - ok = match("rue", 3); - break; - case 'f': - token.type_ = tokenFalse; - ok = match("alse", 4); - break; - case 'n': - token.type_ = tokenNull; - ok = match("ull", 3); - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: - ok = false; - break; - } - if (!ok) - token.type_ = tokenError; - token.end_ = current_; - return true; -} - -void Reader::skipSpaces() { - while (current_ != end_) { - Char c = *current_; - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - ++current_; - else - break; - } -} - -bool Reader::match(Location pattern, int patternLength) { - if (end_ - current_ < patternLength) - return false; - int index = patternLength; - while (index--) - if (current_[index] != pattern[index]) - return false; - current_ += patternLength; - return true; -} - -bool Reader::readComment() { - Location commentBegin = current_ - 1; - Char c = getNextChar(); - bool successful = false; - if (c == '*') - successful = readCStyleComment(); - else if (c == '/') - successful = readCppStyleComment(); - if (!successful) - return false; - - if (collectComments_) { - CommentPlacement placement = commentBefore; - if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { - if (c != '*' || !containsNewLine(commentBegin, current_)) - placement = commentAfterOnSameLine; - } - - addComment(commentBegin, current_, placement); - } - return true; -} - -void -Reader::addComment(Location begin, Location end, CommentPlacement placement) { - assert(collectComments_); - if (placement == commentAfterOnSameLine) { - assert(lastValue_ != 0); - lastValue_->setComment(std::string(begin, end), placement); - } else { - commentsBefore_ += std::string(begin, end); - } -} - -bool Reader::readCStyleComment() { - while (current_ != end_) { - Char c = getNextChar(); - if (c == '*' && *current_ == '/') - break; - } - return getNextChar() == '/'; -} - -bool Reader::readCppStyleComment() { - while (current_ != end_) { - Char c = getNextChar(); - if (c == '\r' || c == '\n') - break; - } - return true; -} - -void Reader::readNumber() { - while (current_ != end_) { - if (!(*current_ >= '0' && *current_ <= '9') && - !in(*current_, '.', 'e', 'E', '+', '-')) - break; - ++current_; - } -} - -bool Reader::readString() { - Char c = 0; - while (current_ != end_) { - c = getNextChar(); - if (c == '\\') - getNextChar(); - else if (c == '"') - break; - } - return c == '"'; -} - -bool Reader::readObject(Token& tokenStart) { - Token tokenName; - std::string name; - currentValue() = Value(objectValue); - currentValue().setOffsetStart(tokenStart.start_ - begin_); - while (readToken(tokenName)) { - bool initialTokenOk = true; - while (tokenName.type_ == tokenComment && initialTokenOk) - initialTokenOk = readToken(tokenName); - if (!initialTokenOk) - break; - if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object - return true; - name = ""; - if (tokenName.type_ == tokenString) { - if (!decodeString(tokenName, name)) - return recoverFromError(tokenObjectEnd); - } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { - Value numberName; - if (!decodeNumber(tokenName, numberName)) - return recoverFromError(tokenObjectEnd); - name = numberName.asString(); - } else { - break; - } - - Token colon; - if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover( - "Missing ':' after object member name", colon, tokenObjectEnd); - } - Value& value = currentValue()[name]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenObjectEnd); - - Token comma; - if (!readToken(comma) || - (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && - comma.type_ != tokenComment)) { - return addErrorAndRecover( - "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); - } - bool finalizeTokenOk = true; - while (comma.type_ == tokenComment && finalizeTokenOk) - finalizeTokenOk = readToken(comma); - if (comma.type_ == tokenObjectEnd) - return true; - } - return addErrorAndRecover( - "Missing '}' or object member name", tokenName, tokenObjectEnd); -} - -bool Reader::readArray(Token& tokenStart) { - currentValue() = Value(arrayValue); - currentValue().setOffsetStart(tokenStart.start_ - begin_); - skipSpaces(); - if (*current_ == ']') // empty array - { - Token endArray; - readToken(endArray); - return true; - } - int index = 0; - for (;;) { - Value& value = currentValue()[index++]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenArrayEnd); - - Token token; - // Accept Comment after last item in the array. - ok = readToken(token); - while (token.type_ == tokenComment && ok) { - ok = readToken(token); - } - bool badTokenType = - (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); - if (!ok || badTokenType) { - return addErrorAndRecover( - "Missing ',' or ']' in array declaration", token, tokenArrayEnd); - } - if (token.type_ == tokenArrayEnd) - break; - } - return true; -} - -bool Reader::decodeNumber(Token& token) { - Value decoded; - if (!decodeNumber(token, decoded)) - return false; - currentValue() = decoded; - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeNumber(Token& token, Value& decoded) { - bool isDouble = false; - for (Location inspect = token.start_; inspect != token.end_; ++inspect) { - isDouble = isDouble || in(*inspect, '.', 'e', 'E', '+') || - (*inspect == '-' && inspect != token.start_); - } - if (isDouble) - return decodeDouble(token, decoded); - // Attempts to parse the number as an integer. If the number is - // larger than the maximum supported value of an integer then - // we decode the number as a double. - Location current = token.start_; - bool isNegative = *current == '-'; - if (isNegative) - ++current; - Value::LargestUInt maxIntegerValue = - isNegative ? Value::LargestUInt(-Value::minLargestInt) - : Value::maxLargestUInt; - Value::LargestUInt threshold = maxIntegerValue / 10; - Value::LargestUInt value = 0; - while (current < token.end_) { - Char c = *current++; - if (c < '0' || c > '9') - return addError("'" + std::string(token.start_, token.end_) + - "' is not a number.", - token); - Value::UInt digit(c - '0'); - if (value >= threshold) { - // We've hit or exceeded the max value divided by 10 (rounded down). If - // a) we've only just touched the limit, b) this is the last digit, and - // c) it's small enough to fit in that rounding delta, we're okay. - // Otherwise treat this number as a double to avoid overflow. - if (value > threshold || current != token.end_ || - digit > maxIntegerValue % 10) { - return decodeDouble(token, decoded); - } - } - value = value * 10 + digit; - } - if (isNegative) - decoded = -Value::LargestInt(value); - else if (value <= Value::LargestUInt(Value::maxInt)) - decoded = Value::LargestInt(value); - else - decoded = value; - return true; -} - -bool Reader::decodeDouble(Token& token) { - Value decoded; - if (!decodeDouble(token, decoded)) - return false; - currentValue() = decoded; - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeDouble(Token& token, Value& decoded) { - double value = 0; - const int bufferSize = 32; - int count; - int length = int(token.end_ - token.start_); - - // Sanity check to avoid buffer overflow exploits. - if (length < 0) { - return addError("Unable to parse token length", token); - } - - // Avoid using a string constant for the format control string given to - // sscanf, as this can cause hard to debug crashes on OS X. See here for more - // info: - // - // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html - char format[] = "%lf"; - - if (length <= bufferSize) { - Char buffer[bufferSize + 1]; - memcpy(buffer, token.start_, length); - buffer[length] = 0; - count = sscanf(buffer, format, &value); - } else { - std::string buffer(token.start_, token.end_); - count = sscanf(buffer.c_str(), format, &value); - } - - if (count != 1) - return addError("'" + std::string(token.start_, token.end_) + - "' is not a number.", - token); - decoded = value; - return true; -} - -bool Reader::decodeString(Token& token) { - std::string decoded; - if (!decodeString(token, decoded)) - return false; - currentValue() = decoded; - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeString(Token& token, std::string& decoded) { - decoded.reserve(token.end_ - token.start_ - 2); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' - while (current != end) { - Char c = *current++; - if (c == '"') - break; - else if (c == '\\') { - if (current == end) - return addError("Empty escape sequence in string", token, current); - Char escape = *current++; - switch (escape) { - case '"': - decoded += '"'; - break; - case '/': - decoded += '/'; - break; - case '\\': - decoded += '\\'; - break; - case 'b': - decoded += '\b'; - break; - case 'f': - decoded += '\f'; - break; - case 'n': - decoded += '\n'; - break; - case 'r': - decoded += '\r'; - break; - case 't': - decoded += '\t'; - break; - case 'u': { - unsigned int unicode; - if (!decodeUnicodeCodePoint(token, current, end, unicode)) - return false; - decoded += codePointToUTF8(unicode); - } break; - default: - return addError("Bad escape sequence in string", token, current); - } - } else { - decoded += c; - } - } - return true; -} - -bool Reader::decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode) { - - if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) - return false; - if (unicode >= 0xD800 && unicode <= 0xDBFF) { - // surrogate pairs - if (end - current < 6) - return addError( - "additional six characters expected to parse unicode surrogate pair.", - token, - current); - unsigned int surrogatePair; - if (*(current++) == '\\' && *(current++) == 'u') { - if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { - unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); - } else - return false; - } else - return addError("expecting another \\u token to begin the second half of " - "a unicode surrogate pair", - token, - current); - } - return true; -} - -bool Reader::decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& unicode) { - if (end - current < 4) - return addError( - "Bad unicode escape sequence in string: four digits expected.", - token, - current); - unicode = 0; - for (int index = 0; index < 4; ++index) { - Char c = *current++; - unicode *= 16; - if (c >= '0' && c <= '9') - unicode += c - '0'; - else if (c >= 'a' && c <= 'f') - unicode += c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - unicode += c - 'A' + 10; - else - return addError( - "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, - current); - } - return true; -} - -bool -Reader::addError(const std::string& message, Token& token, Location extra) { - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = extra; - errors_.push_back(info); - return false; -} - -bool Reader::recoverFromError(TokenType skipUntilToken) { - int errorCount = int(errors_.size()); - Token skip; - for (;;) { - if (!readToken(skip)) - errors_.resize(errorCount); // discard errors caused by recovery - if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) - break; - } - errors_.resize(errorCount); - return false; -} - -bool Reader::addErrorAndRecover(const std::string& message, - Token& token, - TokenType skipUntilToken) { - addError(message, token); - return recoverFromError(skipUntilToken); -} - -Value& Reader::currentValue() { return *(nodes_.top()); } - -Reader::Char Reader::getNextChar() { - if (current_ == end_) - return 0; - return *current_++; -} - -void Reader::getLocationLineAndColumn(Location location, - int& line, - int& column) const { - Location current = begin_; - Location lastLineStart = current; - line = 0; - while (current < location && current != end_) { - Char c = *current++; - if (c == '\r') { - if (*current == '\n') - ++current; - lastLineStart = current; - ++line; - } else if (c == '\n') { - lastLineStart = current; - ++line; - } - } - // column & line start at 1 - column = int(location - lastLineStart) + 1; - ++line; -} - -std::string Reader::getLocationLineAndColumn(Location location) const { - int line, column; - getLocationLineAndColumn(location, line, column); - char buffer[18 + 16 + 16 + 1]; -#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) -#if defined(WINCE) - _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); -#else - sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column); -#endif -#else - snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); -#endif - return buffer; -} - -// Deprecated. Preserved for backward compatibility -std::string Reader::getFormatedErrorMessages() const { - return getFormattedErrorMessages(); -} - -std::string Reader::getFormattedErrorMessages() const { - std::string formattedMessage; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; - formattedMessage += - "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; - formattedMessage += " " + error.message_ + "\n"; - if (error.extra_) - formattedMessage += - "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; - } - return formattedMessage; -} - -std::vector Reader::getStructuredErrors() const { - std::vector allErrors; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; - Reader::StructuredError structured; - structured.offset_start = error.token_.start_ - begin_; - structured.offset_limit = error.token_.end_ - begin_; - structured.message = error.message_; - allErrors.push_back(structured); - } - return allErrors; -} - -std::istream& operator>>(std::istream& sin, Value& root) { - Json::Reader reader; - bool ok = reader.parse(sin, root, true); - if (!ok) { - fprintf(stderr, - "Error from reader: %s", - reader.getFormattedErrorMessages().c_str()); - - JSON_FAIL_MESSAGE("reader error"); - } - return sin; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_reader.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_batchallocator.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED -#define JSONCPP_BATCHALLOCATOR_H_INCLUDED - -#include -#include - -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - -namespace Json { - -/* Fast memory allocator. - * - * This memory allocator allocates memory for a batch of object (specified by - * the page size, the number of object in each page). - * - * It does not allow the destruction of a single object. All the allocated - * objects can be destroyed at once. The memory can be either released or reused - * for future allocation. - * - * The in-place new operator must be used to construct the object using the - * pointer returned by allocate. - */ -template -class BatchAllocator { -public: - BatchAllocator(unsigned int objectsPerPage = 255) - : freeHead_(0), objectsPerPage_(objectsPerPage) { - // printf( "Size: %d => %s\n", sizeof(AllocatedType), - // typeid(AllocatedType).name() ); - assert(sizeof(AllocatedType) * objectPerAllocation >= - sizeof(AllocatedType*)); // We must be able to store a slist in the - // object free space. - assert(objectsPerPage >= 16); - batches_ = allocateBatch(0); // allocated a dummy page - currentBatch_ = batches_; - } - - ~BatchAllocator() { - for (BatchInfo* batch = batches_; batch;) { - BatchInfo* nextBatch = batch->next_; - free(batch); - batch = nextBatch; - } - } - - /// allocate space for an array of objectPerAllocation object. - /// @warning it is the responsability of the caller to call objects - /// constructors. - AllocatedType* allocate() { - if (freeHead_) // returns node from free list. - { - AllocatedType* object = freeHead_; - freeHead_ = *(AllocatedType**)object; - return object; - } - if (currentBatch_->used_ == currentBatch_->end_) { - currentBatch_ = currentBatch_->next_; - while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_) - currentBatch_ = currentBatch_->next_; - - if (!currentBatch_) // no free batch found, allocate a new one - { - currentBatch_ = allocateBatch(objectsPerPage_); - currentBatch_->next_ = batches_; // insert at the head of the list - batches_ = currentBatch_; - } - } - AllocatedType* allocated = currentBatch_->used_; - currentBatch_->used_ += objectPerAllocation; - return allocated; - } - - /// Release the object. - /// @warning it is the responsability of the caller to actually destruct the - /// object. - void release(AllocatedType* object) { - assert(object != 0); - *(AllocatedType**)object = freeHead_; - freeHead_ = object; - } - -private: - struct BatchInfo { - BatchInfo* next_; - AllocatedType* used_; - AllocatedType* end_; - AllocatedType buffer_[objectPerAllocation]; - }; - - // disabled copy constructor and assignement operator. - BatchAllocator(const BatchAllocator&); - void operator=(const BatchAllocator&); - - static BatchInfo* allocateBatch(unsigned int objectsPerPage) { - const unsigned int mallocSize = - sizeof(BatchInfo) - sizeof(AllocatedType) * objectPerAllocation + - sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; - BatchInfo* batch = static_cast(malloc(mallocSize)); - batch->next_ = 0; - batch->used_ = batch->buffer_; - batch->end_ = batch->buffer_ + objectsPerPage; - return batch; - } - - BatchInfo* batches_; - BatchInfo* currentBatch_; - /// Head of a single linked list within the allocated space of freeed object - AllocatedType* freeHead_; - unsigned int objectsPerPage_; -}; - -} // namespace Json - -#endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION - -#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_batchallocator.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_valueiterator.inl -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -// included by json_value.cpp - -namespace Json { - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIteratorBase -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIteratorBase::ValueIteratorBase() -#ifndef JSON_VALUE_USE_INTERNAL_MAP - : current_(), isNull_(true) { -} -#else - : isArray_(true), isNull_(true) { - iterator_.array_ = ValueInternalArray::IteratorState(); -} -#endif - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueIteratorBase::ValueIteratorBase( - const Value::ObjectValues::iterator& current) - : current_(current), isNull_(false) {} -#else -ValueIteratorBase::ValueIteratorBase( - const ValueInternalArray::IteratorState& state) - : isArray_(true) { - iterator_.array_ = state; -} - -ValueIteratorBase::ValueIteratorBase( - const ValueInternalMap::IteratorState& state) - : isArray_(false) { - iterator_.map_ = state; -} -#endif - -Value& ValueIteratorBase::deref() const { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - return current_->second; -#else - if (isArray_) - return ValueInternalArray::dereference(iterator_.array_); - return ValueInternalMap::value(iterator_.map_); -#endif -} - -void ValueIteratorBase::increment() { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ++current_; -#else - if (isArray_) - ValueInternalArray::increment(iterator_.array_); - ValueInternalMap::increment(iterator_.map_); -#endif -} - -void ValueIteratorBase::decrement() { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - --current_; -#else - if (isArray_) - ValueInternalArray::decrement(iterator_.array_); - ValueInternalMap::decrement(iterator_.map_); -#endif -} - -ValueIteratorBase::difference_type -ValueIteratorBase::computeDistance(const SelfType& other) const { -#ifndef JSON_VALUE_USE_INTERNAL_MAP -#ifdef JSON_USE_CPPTL_SMALLMAP - return current_ - other.current_; -#else - // Iterator for null value are initialized using the default - // constructor, which initialize current_ to the default - // std::map::iterator. As begin() and end() are two instance - // of the default std::map::iterator, they can not be compared. - // To allow this, we handle this comparison specifically. - if (isNull_ && other.isNull_) { - return 0; - } - - // Usage of std::distance is not portable (does not compile with Sun Studio 12 - // RogueWave STL, - // which is the one used by default). - // Using a portable hand-made version for non random iterator instead: - // return difference_type( std::distance( current_, other.current_ ) ); - difference_type myDistance = 0; - for (Value::ObjectValues::iterator it = current_; it != other.current_; - ++it) { - ++myDistance; - } - return myDistance; -#endif -#else - if (isArray_) - return ValueInternalArray::distance(iterator_.array_, - other.iterator_.array_); - return ValueInternalMap::distance(iterator_.map_, other.iterator_.map_); -#endif -} - -bool ValueIteratorBase::isEqual(const SelfType& other) const { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - if (isNull_) { - return other.isNull_; - } - return current_ == other.current_; -#else - if (isArray_) - return ValueInternalArray::equals(iterator_.array_, other.iterator_.array_); - return ValueInternalMap::equals(iterator_.map_, other.iterator_.map_); -#endif -} - -void ValueIteratorBase::copy(const SelfType& other) { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - current_ = other.current_; - isNull_ = other.isNull_; -#else - if (isArray_) - iterator_.array_ = other.iterator_.array_; - iterator_.map_ = other.iterator_.map_; -#endif -} - -Value ValueIteratorBase::key() const { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const Value::CZString czstring = (*current_).first; - if (czstring.c_str()) { - if (czstring.isStaticString()) - return Value(StaticString(czstring.c_str())); - return Value(czstring.c_str()); - } - return Value(czstring.index()); -#else - if (isArray_) - return Value(ValueInternalArray::indexOf(iterator_.array_)); - bool isStatic; - const char* memberName = ValueInternalMap::key(iterator_.map_, isStatic); - if (isStatic) - return Value(StaticString(memberName)); - return Value(memberName); -#endif -} - -UInt ValueIteratorBase::index() const { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const Value::CZString czstring = (*current_).first; - if (!czstring.c_str()) - return czstring.index(); - return Value::UInt(-1); -#else - if (isArray_) - return Value::UInt(ValueInternalArray::indexOf(iterator_.array_)); - return Value::UInt(-1); -#endif -} - -const char* ValueIteratorBase::memberName() const { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const char* name = (*current_).first.c_str(); - return name ? name : ""; -#else - if (!isArray_) - return ValueInternalMap::key(iterator_.map_); - return ""; -#endif -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueConstIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueConstIterator::ValueConstIterator() {} - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueConstIterator::ValueConstIterator( - const Value::ObjectValues::iterator& current) - : ValueIteratorBase(current) {} -#else -ValueConstIterator::ValueConstIterator( - const ValueInternalArray::IteratorState& state) - : ValueIteratorBase(state) {} - -ValueConstIterator::ValueConstIterator( - const ValueInternalMap::IteratorState& state) - : ValueIteratorBase(state) {} -#endif - -ValueConstIterator& ValueConstIterator:: -operator=(const ValueIteratorBase& other) { - copy(other); - return *this; -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIterator::ValueIterator() {} - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) - : ValueIteratorBase(current) {} -#else -ValueIterator::ValueIterator(const ValueInternalArray::IteratorState& state) - : ValueIteratorBase(state) {} - -ValueIterator::ValueIterator(const ValueInternalMap::IteratorState& state) - : ValueIteratorBase(state) {} -#endif - -ValueIterator::ValueIterator(const ValueConstIterator& other) - : ValueIteratorBase(other) {} - -ValueIterator::ValueIterator(const ValueIterator& other) - : ValueIteratorBase(other) {} - -ValueIterator& ValueIterator::operator=(const SelfType& other) { - copy(other); - return *this; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_valueiterator.inl -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_value.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2011 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR -#include "json_batchallocator.h" -#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#ifdef JSON_USE_CPPTL -#include -#endif -#include // size_t - -#define JSON_ASSERT_UNREACHABLE assert(false) - -namespace Json { - -// This is a walkaround to avoid the static initialization of Value::null. -// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of -// 8 (instead of 4) as a bit of future-proofing. -#if defined(__ARMEL__) -#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) -#else -#define ALIGNAS(byte_alignment) -#endif -static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; -const unsigned char& kNullRef = kNull[0]; -const Value& Value::null = reinterpret_cast(kNullRef); - -const Int Value::minInt = Int(~(UInt(-1) / 2)); -const Int Value::maxInt = Int(UInt(-1) / 2); -const UInt Value::maxUInt = UInt(-1); -#if defined(JSON_HAS_INT64) -const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); -const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); -const UInt64 Value::maxUInt64 = UInt64(-1); -// The constant is hard-coded because some compiler have trouble -// converting Value::maxUInt64 to a double correctly (AIX/xlC). -// Assumes that UInt64 is a 64 bits integer. -static const double maxUInt64AsDouble = 18446744073709551615.0; -#endif // defined(JSON_HAS_INT64) -const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); -const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); -const LargestUInt Value::maxLargestUInt = LargestUInt(-1); - -/// Unknown size marker -static const unsigned int unknown = (unsigned)-1; - -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) -template -static inline bool InRange(double d, T min, U max) { - return d >= min && d <= max; -} -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) -static inline double integerToDouble(Json::UInt64 value) { - return static_cast(Int64(value / 2)) * 2.0 + Int64(value & 1); -} - -template static inline double integerToDouble(T value) { - return static_cast(value); -} - -template -static inline bool InRange(double d, T min, U max) { - return d >= integerToDouble(min) && d <= integerToDouble(max); -} -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - -/** Duplicates the specified string value. - * @param value Pointer to the string to duplicate. Must be zero-terminated if - * length is "unknown". - * @param length Length of the value. if equals to unknown, then it will be - * computed using strlen(value). - * @return Pointer on the duplicate instance of string. - */ -static inline char* duplicateStringValue(const char* value, - unsigned int length = unknown) { - if (length == unknown) - length = (unsigned int)strlen(value); - - // Avoid an integer overflow in the call to malloc below by limiting length - // to a sane value. - if (length >= (unsigned)Value::maxInt) - length = Value::maxInt - 1; - - char* newString = static_cast(malloc(length + 1)); - JSON_ASSERT_MESSAGE(newString != 0, - "in Json::Value::duplicateStringValue(): " - "Failed to allocate string value buffer"); - memcpy(newString, value, length); - newString[length] = 0; - return newString; -} - -/** Free the string duplicated by duplicateStringValue(). - */ -static inline void releaseStringValue(char* value) { free(value); } - -} // namespace Json - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ValueInternals... -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -#if !defined(JSON_IS_AMALGAMATION) -#ifdef JSON_VALUE_USE_INTERNAL_MAP -#include "json_internalarray.inl" -#include "json_internalmap.inl" -#endif // JSON_VALUE_USE_INTERNAL_MAP - -#include "json_valueiterator.inl" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CommentInfo -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -Value::CommentInfo::CommentInfo() : comment_(0) {} - -Value::CommentInfo::~CommentInfo() { - if (comment_) - releaseStringValue(comment_); -} - -void Value::CommentInfo::setComment(const char* text) { - if (comment_) - releaseStringValue(comment_); - JSON_ASSERT(text != 0); - JSON_ASSERT_MESSAGE( - text[0] == '\0' || text[0] == '/', - "in Json::Value::setComment(): Comments must start with /"); - // It seems that /**/ style comments are acceptable as well. - comment_ = duplicateStringValue(text); -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CZString -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -#ifndef JSON_VALUE_USE_INTERNAL_MAP - -// Notes: index_ indicates if the string was allocated when -// a string is stored. - -Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {} - -Value::CZString::CZString(const char* cstr, DuplicationPolicy allocate) - : cstr_(allocate == duplicate ? duplicateStringValue(cstr) : cstr), - index_(allocate) {} - -Value::CZString::CZString(const CZString& other) - : cstr_(other.index_ != noDuplication && other.cstr_ != 0 - ? duplicateStringValue(other.cstr_) - : other.cstr_), - index_(other.cstr_ - ? (other.index_ == noDuplication ? noDuplication : duplicate) - : other.index_) {} - -Value::CZString::~CZString() { - if (cstr_ && index_ == duplicate) - releaseStringValue(const_cast(cstr_)); -} - -void Value::CZString::swap(CZString& other) { - std::swap(cstr_, other.cstr_); - std::swap(index_, other.index_); -} - -Value::CZString& Value::CZString::operator=(CZString other) { - swap(other); - return *this; -} - -bool Value::CZString::operator<(const CZString& other) const { - if (cstr_) - return strcmp(cstr_, other.cstr_) < 0; - return index_ < other.index_; -} - -bool Value::CZString::operator==(const CZString& other) const { - if (cstr_) - return strcmp(cstr_, other.cstr_) == 0; - return index_ == other.index_; -} - -ArrayIndex Value::CZString::index() const { return index_; } - -const char* Value::CZString::c_str() const { return cstr_; } - -bool Value::CZString::isStaticString() const { return index_ == noDuplication; } - -#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::Value -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -/*! \internal Default constructor initialization must be equivalent to: - * memset( this, 0, sizeof(Value) ) - * This optimization is used in ValueInternalMap fast allocator. - */ -Value::Value(ValueType type) - : type_(type), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - switch (type) { - case nullValue: - break; - case intValue: - case uintValue: - value_.int_ = 0; - break; - case realValue: - value_.real_ = 0.0; - break; - case stringValue: - value_.string_ = 0; - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(); - break; -#else - case arrayValue: - value_.array_ = arrayAllocator()->newArray(); - break; - case objectValue: - value_.map_ = mapAllocator()->newMap(); - break; -#endif - case booleanValue: - value_.bool_ = false; - break; - default: - JSON_ASSERT_UNREACHABLE; - } -} - -Value::Value(UInt value) - : type_(uintValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.uint_ = value; -} - -Value::Value(Int value) - : type_(intValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.int_ = value; -} - -#if defined(JSON_HAS_INT64) -Value::Value(Int64 value) - : type_(intValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.int_ = value; -} - -Value::Value(UInt64 value) - : type_(uintValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.uint_ = value; -} -#endif // defined(JSON_HAS_INT64) - -Value::Value(double value) - : type_(realValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.real_ = value; -} - -Value::Value(const char* value) - : type_(stringValue), allocated_(true) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.string_ = duplicateStringValue(value); -} - -Value::Value(const char* beginValue, const char* endValue) - : type_(stringValue), allocated_(true) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.string_ = - duplicateStringValue(beginValue, (unsigned int)(endValue - beginValue)); -} - -Value::Value(const std::string& value) - : type_(stringValue), allocated_(true) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.string_ = - duplicateStringValue(value.c_str(), (unsigned int)value.length()); -} - -Value::Value(const StaticString& value) - : type_(stringValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.string_ = const_cast(value.c_str()); -} - -#ifdef JSON_USE_CPPTL -Value::Value(const CppTL::ConstString& value) - : type_(stringValue), allocated_(true) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.string_ = duplicateStringValue(value, value.length()); -} -#endif - -Value::Value(bool value) - : type_(booleanValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.bool_ = value; -} - -Value::Value(const Value& other) - : type_(other.type_), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(other.start_), limit_(other.limit_) { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - value_ = other.value_; - break; - case stringValue: - if (other.value_.string_) { - value_.string_ = duplicateStringValue(other.value_.string_); - allocated_ = true; - } else { - value_.string_ = 0; - allocated_ = false; - } - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(*other.value_.map_); - break; -#else - case arrayValue: - value_.array_ = arrayAllocator()->newArrayCopy(*other.value_.array_); - break; - case objectValue: - value_.map_ = mapAllocator()->newMapCopy(*other.value_.map_); - break; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - if (other.comments_) { - comments_ = new CommentInfo[numberOfCommentPlacement]; - for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { - const CommentInfo& otherComment = other.comments_[comment]; - if (otherComment.comment_) - comments_[comment].setComment(otherComment.comment_); - } - } -} - -Value::~Value() { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if (allocated_) - releaseStringValue(value_.string_); - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - delete value_.map_; - break; -#else - case arrayValue: - arrayAllocator()->destructArray(value_.array_); - break; - case objectValue: - mapAllocator()->destructMap(value_.map_); - break; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - - if (comments_) - delete[] comments_; -} - -Value& Value::operator=(Value other) { - swap(other); - return *this; -} - -void Value::swap(Value& other) { - ValueType temp = type_; - type_ = other.type_; - other.type_ = temp; - std::swap(value_, other.value_); - int temp2 = allocated_; - allocated_ = other.allocated_; - other.allocated_ = temp2; - std::swap(start_, other.start_); - std::swap(limit_, other.limit_); -} - -ValueType Value::type() const { return type_; } - -int Value::compare(const Value& other) const { - if (*this < other) - return -1; - if (*this > other) - return 1; - return 0; -} - -bool Value::operator<(const Value& other) const { - int typeDelta = type_ - other.type_; - if (typeDelta) - return typeDelta < 0 ? true : false; - switch (type_) { - case nullValue: - return false; - case intValue: - return value_.int_ < other.value_.int_; - case uintValue: - return value_.uint_ < other.value_.uint_; - case realValue: - return value_.real_ < other.value_.real_; - case booleanValue: - return value_.bool_ < other.value_.bool_; - case stringValue: - return (value_.string_ == 0 && other.value_.string_) || - (other.value_.string_ && value_.string_ && - strcmp(value_.string_, other.value_.string_) < 0); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: { - int delta = int(value_.map_->size() - other.value_.map_->size()); - if (delta) - return delta < 0; - return (*value_.map_) < (*other.value_.map_); - } -#else - case arrayValue: - return value_.array_->compare(*(other.value_.array_)) < 0; - case objectValue: - return value_.map_->compare(*(other.value_.map_)) < 0; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool Value::operator<=(const Value& other) const { return !(other < *this); } - -bool Value::operator>=(const Value& other) const { return !(*this < other); } - -bool Value::operator>(const Value& other) const { return other < *this; } - -bool Value::operator==(const Value& other) const { - // if ( type_ != other.type_ ) - // GCC 2.95.3 says: - // attempt to take address of bit-field structure member `Json::Value::type_' - // Beats me, but a temp solves the problem. - int temp = other.type_; - if (type_ != temp) - return false; - switch (type_) { - case nullValue: - return true; - case intValue: - return value_.int_ == other.value_.int_; - case uintValue: - return value_.uint_ == other.value_.uint_; - case realValue: - return value_.real_ == other.value_.real_; - case booleanValue: - return value_.bool_ == other.value_.bool_; - case stringValue: - return (value_.string_ == other.value_.string_) || - (other.value_.string_ && value_.string_ && - strcmp(value_.string_, other.value_.string_) == 0); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - return value_.map_->size() == other.value_.map_->size() && - (*value_.map_) == (*other.value_.map_); -#else - case arrayValue: - return value_.array_->compare(*(other.value_.array_)) == 0; - case objectValue: - return value_.map_->compare(*(other.value_.map_)) == 0; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool Value::operator!=(const Value& other) const { return !(*this == other); } - -const char* Value::asCString() const { - JSON_ASSERT_MESSAGE(type_ == stringValue, - "in Json::Value::asCString(): requires stringValue"); - return value_.string_; -} - -std::string Value::asString() const { - switch (type_) { - case nullValue: - return ""; - case stringValue: - return value_.string_ ? value_.string_ : ""; - case booleanValue: - return value_.bool_ ? "true" : "false"; - case intValue: - return valueToString(value_.int_); - case uintValue: - return valueToString(value_.uint_); - case realValue: - return valueToString(value_.real_); - default: - JSON_FAIL_MESSAGE("Type is not convertible to string"); - } -} - -#ifdef JSON_USE_CPPTL -CppTL::ConstString Value::asConstString() const { - return CppTL::ConstString(asString().c_str()); -} -#endif - -Value::Int Value::asInt() const { - switch (type_) { - case intValue: - JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); - return Int(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); - return Int(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), - "double out of Int range"); - return Int(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to Int."); -} - -Value::UInt Value::asUInt() const { - switch (type_) { - case intValue: - JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); - return UInt(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); - return UInt(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), - "double out of UInt range"); - return UInt(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to UInt."); -} - -#if defined(JSON_HAS_INT64) - -Value::Int64 Value::asInt64() const { - switch (type_) { - case intValue: - return Int64(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); - return Int64(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), - "double out of Int64 range"); - return Int64(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to Int64."); -} - -Value::UInt64 Value::asUInt64() const { - switch (type_) { - case intValue: - JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); - return UInt64(value_.int_); - case uintValue: - return UInt64(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), - "double out of UInt64 range"); - return UInt64(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); -} -#endif // if defined(JSON_HAS_INT64) - -LargestInt Value::asLargestInt() const { -#if defined(JSON_NO_INT64) - return asInt(); -#else - return asInt64(); -#endif -} - -LargestUInt Value::asLargestUInt() const { -#if defined(JSON_NO_INT64) - return asUInt(); -#else - return asUInt64(); -#endif -} - -double Value::asDouble() const { - switch (type_) { - case intValue: - return static_cast(value_.int_); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast(value_.uint_); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return integerToDouble(value_.uint_); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return value_.real_; - case nullValue: - return 0.0; - case booleanValue: - return value_.bool_ ? 1.0 : 0.0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to double."); -} - -float Value::asFloat() const { - switch (type_) { - case intValue: - return static_cast(value_.int_); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast(value_.uint_); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return integerToDouble(value_.uint_); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return static_cast(value_.real_); - case nullValue: - return 0.0; - case booleanValue: - return value_.bool_ ? 1.0f : 0.0f; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to float."); -} - -bool Value::asBool() const { - switch (type_) { - case booleanValue: - return value_.bool_; - case nullValue: - return false; - case intValue: - return value_.int_ ? true : false; - case uintValue: - return value_.uint_ ? true : false; - case realValue: - return value_.real_ ? true : false; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to bool."); -} - -bool Value::isConvertibleTo(ValueType other) const { - switch (other) { - case nullValue: - return (isNumeric() && asDouble() == 0.0) || - (type_ == booleanValue && value_.bool_ == false) || - (type_ == stringValue && asString() == "") || - (type_ == arrayValue && value_.map_->size() == 0) || - (type_ == objectValue && value_.map_->size() == 0) || - type_ == nullValue; - case intValue: - return isInt() || - (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || - type_ == booleanValue || type_ == nullValue; - case uintValue: - return isUInt() || - (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || - type_ == booleanValue || type_ == nullValue; - case realValue: - return isNumeric() || type_ == booleanValue || type_ == nullValue; - case booleanValue: - return isNumeric() || type_ == booleanValue || type_ == nullValue; - case stringValue: - return isNumeric() || type_ == booleanValue || type_ == stringValue || - type_ == nullValue; - case arrayValue: - return type_ == arrayValue || type_ == nullValue; - case objectValue: - return type_ == objectValue || type_ == nullValue; - } - JSON_ASSERT_UNREACHABLE; - return false; -} - -/// Number of values in array or object -ArrayIndex Value::size() const { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - case stringValue: - return 0; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: // size of the array is highest index + 1 - if (!value_.map_->empty()) { - ObjectValues::const_iterator itLast = value_.map_->end(); - --itLast; - return (*itLast).first.index() + 1; - } - return 0; - case objectValue: - return ArrayIndex(value_.map_->size()); -#else - case arrayValue: - return Int(value_.array_->size()); - case objectValue: - return Int(value_.map_->size()); -#endif - } - JSON_ASSERT_UNREACHABLE; - return 0; // unreachable; -} - -bool Value::empty() const { - if (isNull() || isArray() || isObject()) - return size() == 0u; - else - return false; -} - -bool Value::operator!() const { return isNull(); } - -void Value::clear() { - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || - type_ == objectValue, - "in Json::Value::clear(): requires complex value"); - start_ = 0; - limit_ = 0; - switch (type_) { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_->clear(); - break; -#else - case arrayValue: - value_.array_->clear(); - break; - case objectValue: - value_.map_->clear(); - break; -#endif - default: - break; - } -} - -void Value::resize(ArrayIndex newSize) { - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, - "in Json::Value::resize(): requires arrayValue"); - if (type_ == nullValue) - *this = Value(arrayValue); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ArrayIndex oldSize = size(); - if (newSize == 0) - clear(); - else if (newSize > oldSize) - (*this)[newSize - 1]; - else { - for (ArrayIndex index = newSize; index < oldSize; ++index) { - value_.map_->erase(index); - } - assert(size() == newSize); - } -#else - value_.array_->resize(newSize); -#endif -} - -Value& Value::operator[](ArrayIndex index) { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == arrayValue, - "in Json::Value::operator[](ArrayIndex): requires arrayValue"); - if (type_ == nullValue) - *this = Value(arrayValue); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString key(index); - ObjectValues::iterator it = value_.map_->lower_bound(key); - if (it != value_.map_->end() && (*it).first == key) - return (*it).second; - - ObjectValues::value_type defaultValue(key, null); - it = value_.map_->insert(it, defaultValue); - return (*it).second; -#else - return value_.array_->resolveReference(index); -#endif -} - -Value& Value::operator[](int index) { - JSON_ASSERT_MESSAGE( - index >= 0, - "in Json::Value::operator[](int index): index cannot be negative"); - return (*this)[ArrayIndex(index)]; -} - -const Value& Value::operator[](ArrayIndex index) const { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == arrayValue, - "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); - if (type_ == nullValue) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString key(index); - ObjectValues::const_iterator it = value_.map_->find(key); - if (it == value_.map_->end()) - return null; - return (*it).second; -#else - Value* value = value_.array_->find(index); - return value ? *value : null; -#endif -} - -const Value& Value::operator[](int index) const { - JSON_ASSERT_MESSAGE( - index >= 0, - "in Json::Value::operator[](int index) const: index cannot be negative"); - return (*this)[ArrayIndex(index)]; -} - -Value& Value::operator[](const char* key) { - return resolveReference(key, false); -} - -Value& Value::resolveReference(const char* key, bool isStatic) { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::resolveReference(): requires objectValue"); - if (type_ == nullValue) - *this = Value(objectValue); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey( - key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy); - ObjectValues::iterator it = value_.map_->lower_bound(actualKey); - if (it != value_.map_->end() && (*it).first == actualKey) - return (*it).second; - - ObjectValues::value_type defaultValue(actualKey, null); - it = value_.map_->insert(it, defaultValue); - Value& value = (*it).second; - return value; -#else - return value_.map_->resolveReference(key, isStatic); -#endif -} - -Value Value::get(ArrayIndex index, const Value& defaultValue) const { - const Value* value = &((*this)[index]); - return value == &null ? defaultValue : *value; -} - -bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } - -const Value& Value::operator[](const char* key) const { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::operator[](char const*)const: requires objectValue"); - if (type_ == nullValue) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey(key, CZString::noDuplication); - ObjectValues::const_iterator it = value_.map_->find(actualKey); - if (it == value_.map_->end()) - return null; - return (*it).second; -#else - const Value* value = value_.map_->find(key); - return value ? *value : null; -#endif -} - -Value& Value::operator[](const std::string& key) { - return (*this)[key.c_str()]; -} - -const Value& Value::operator[](const std::string& key) const { - return (*this)[key.c_str()]; -} - -Value& Value::operator[](const StaticString& key) { - return resolveReference(key, true); -} - -#ifdef JSON_USE_CPPTL -Value& Value::operator[](const CppTL::ConstString& key) { - return (*this)[key.c_str()]; -} - -const Value& Value::operator[](const CppTL::ConstString& key) const { - return (*this)[key.c_str()]; -} -#endif - -Value& Value::append(const Value& value) { return (*this)[size()] = value; } - -Value Value::get(const char* key, const Value& defaultValue) const { - const Value* value = &((*this)[key]); - return value == &null ? defaultValue : *value; -} - -Value Value::get(const std::string& key, const Value& defaultValue) const { - return get(key.c_str(), defaultValue); -} - -Value Value::removeMember(const char* key) { - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, - "in Json::Value::removeMember(): requires objectValue"); - if (type_ == nullValue) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey(key, CZString::noDuplication); - ObjectValues::iterator it = value_.map_->find(actualKey); - if (it == value_.map_->end()) - return null; - Value old(it->second); - value_.map_->erase(it); - return old; -#else - Value* value = value_.map_->find(key); - if (value) { - Value old(*value); - value_.map_.remove(key); - return old; - } else { - return null; - } -#endif -} - -Value Value::removeMember(const std::string& key) { - return removeMember(key.c_str()); -} - -#ifdef JSON_USE_CPPTL -Value Value::get(const CppTL::ConstString& key, - const Value& defaultValue) const { - return get(key.c_str(), defaultValue); -} -#endif - -bool Value::isMember(const char* key) const { - const Value* value = &((*this)[key]); - return value != &null; -} - -bool Value::isMember(const std::string& key) const { - return isMember(key.c_str()); -} - -#ifdef JSON_USE_CPPTL -bool Value::isMember(const CppTL::ConstString& key) const { - return isMember(key.c_str()); -} -#endif - -Value::Members Value::getMemberNames() const { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::getMemberNames(), value must be objectValue"); - if (type_ == nullValue) - return Value::Members(); - Members members; - members.reserve(value_.map_->size()); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ObjectValues::const_iterator it = value_.map_->begin(); - ObjectValues::const_iterator itEnd = value_.map_->end(); - for (; it != itEnd; ++it) - members.push_back(std::string((*it).first.c_str())); -#else - ValueInternalMap::IteratorState it; - ValueInternalMap::IteratorState itEnd; - value_.map_->makeBeginIterator(it); - value_.map_->makeEndIterator(itEnd); - for (; !ValueInternalMap::equals(it, itEnd); ValueInternalMap::increment(it)) - members.push_back(std::string(ValueInternalMap::key(it))); -#endif - return members; -} -// -//# ifdef JSON_USE_CPPTL -// EnumMemberNames -// Value::enumMemberNames() const -//{ -// if ( type_ == objectValue ) -// { -// return CppTL::Enum::any( CppTL::Enum::transform( -// CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), -// MemberNamesTransform() ) ); -// } -// return EnumMemberNames(); -//} -// -// -// EnumValues -// Value::enumValues() const -//{ -// if ( type_ == objectValue || type_ == arrayValue ) -// return CppTL::Enum::anyValues( *(value_.map_), -// CppTL::Type() ); -// return EnumValues(); -//} -// -//# endif - -static bool IsIntegral(double d) { - double integral_part; - return modf(d, &integral_part) == 0.0; -} - -bool Value::isNull() const { return type_ == nullValue; } - -bool Value::isBool() const { return type_ == booleanValue; } - -bool Value::isInt() const { - switch (type_) { - case intValue: - return value_.int_ >= minInt && value_.int_ <= maxInt; - case uintValue: - return value_.uint_ <= UInt(maxInt); - case realValue: - return value_.real_ >= minInt && value_.real_ <= maxInt && - IsIntegral(value_.real_); - default: - break; - } - return false; -} - -bool Value::isUInt() const { - switch (type_) { - case intValue: - return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); - case uintValue: - return value_.uint_ <= maxUInt; - case realValue: - return value_.real_ >= 0 && value_.real_ <= maxUInt && - IsIntegral(value_.real_); - default: - break; - } - return false; -} - -bool Value::isInt64() const { -#if defined(JSON_HAS_INT64) - switch (type_) { - case intValue: - return true; - case uintValue: - return value_.uint_ <= UInt64(maxInt64); - case realValue: - // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a - // double, so double(maxInt64) will be rounded up to 2^63. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= double(minInt64) && - value_.real_ < double(maxInt64) && IsIntegral(value_.real_); - default: - break; - } -#endif // JSON_HAS_INT64 - return false; -} - -bool Value::isUInt64() const { -#if defined(JSON_HAS_INT64) - switch (type_) { - case intValue: - return value_.int_ >= 0; - case uintValue: - return true; - case realValue: - // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a - // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && - IsIntegral(value_.real_); - default: - break; - } -#endif // JSON_HAS_INT64 - return false; -} - -bool Value::isIntegral() const { -#if defined(JSON_HAS_INT64) - return isInt64() || isUInt64(); -#else - return isInt() || isUInt(); -#endif -} - -bool Value::isDouble() const { return type_ == realValue || isIntegral(); } - -bool Value::isNumeric() const { return isIntegral() || isDouble(); } - -bool Value::isString() const { return type_ == stringValue; } - -bool Value::isArray() const { return type_ == arrayValue; } - -bool Value::isObject() const { return type_ == objectValue; } - -void Value::setComment(const char* comment, CommentPlacement placement) { - if (!comments_) - comments_ = new CommentInfo[numberOfCommentPlacement]; - comments_[placement].setComment(comment); -} - -void Value::setComment(const std::string& comment, CommentPlacement placement) { - setComment(comment.c_str(), placement); -} - -bool Value::hasComment(CommentPlacement placement) const { - return comments_ != 0 && comments_[placement].comment_ != 0; -} - -std::string Value::getComment(CommentPlacement placement) const { - if (hasComment(placement)) - return comments_[placement].comment_; - return ""; -} - -void Value::setOffsetStart(size_t start) { start_ = start; } - -void Value::setOffsetLimit(size_t limit) { limit_ = limit; } - -size_t Value::getOffsetStart() const { return start_; } - -size_t Value::getOffsetLimit() const { return limit_; } - -std::string Value::toStyledString() const { - StyledWriter writer; - return writer.write(*this); -} - -Value::const_iterator Value::begin() const { - switch (type_) { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if (value_.array_) { - ValueInternalArray::IteratorState it; - value_.array_->makeBeginIterator(it); - return const_iterator(it); - } - break; - case objectValue: - if (value_.map_) { - ValueInternalMap::IteratorState it; - value_.map_->makeBeginIterator(it); - return const_iterator(it); - } - break; -#else - case arrayValue: - case objectValue: - if (value_.map_) - return const_iterator(value_.map_->begin()); - break; -#endif - default: - break; - } - return const_iterator(); -} - -Value::const_iterator Value::end() const { - switch (type_) { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if (value_.array_) { - ValueInternalArray::IteratorState it; - value_.array_->makeEndIterator(it); - return const_iterator(it); - } - break; - case objectValue: - if (value_.map_) { - ValueInternalMap::IteratorState it; - value_.map_->makeEndIterator(it); - return const_iterator(it); - } - break; -#else - case arrayValue: - case objectValue: - if (value_.map_) - return const_iterator(value_.map_->end()); - break; -#endif - default: - break; - } - return const_iterator(); -} - -Value::iterator Value::begin() { - switch (type_) { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if (value_.array_) { - ValueInternalArray::IteratorState it; - value_.array_->makeBeginIterator(it); - return iterator(it); - } - break; - case objectValue: - if (value_.map_) { - ValueInternalMap::IteratorState it; - value_.map_->makeBeginIterator(it); - return iterator(it); - } - break; -#else - case arrayValue: - case objectValue: - if (value_.map_) - return iterator(value_.map_->begin()); - break; -#endif - default: - break; - } - return iterator(); -} - -Value::iterator Value::end() { - switch (type_) { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if (value_.array_) { - ValueInternalArray::IteratorState it; - value_.array_->makeEndIterator(it); - return iterator(it); - } - break; - case objectValue: - if (value_.map_) { - ValueInternalMap::IteratorState it; - value_.map_->makeEndIterator(it); - return iterator(it); - } - break; -#else - case arrayValue: - case objectValue: - if (value_.map_) - return iterator(value_.map_->end()); - break; -#endif - default: - break; - } - return iterator(); -} - -// class PathArgument -// ////////////////////////////////////////////////////////////////// - -PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} - -PathArgument::PathArgument(ArrayIndex index) - : key_(), index_(index), kind_(kindIndex) {} - -PathArgument::PathArgument(const char* key) - : key_(key), index_(), kind_(kindKey) {} - -PathArgument::PathArgument(const std::string& key) - : key_(key.c_str()), index_(), kind_(kindKey) {} - -// class Path -// ////////////////////////////////////////////////////////////////// - -Path::Path(const std::string& path, - const PathArgument& a1, - const PathArgument& a2, - const PathArgument& a3, - const PathArgument& a4, - const PathArgument& a5) { - InArgs in; - in.push_back(&a1); - in.push_back(&a2); - in.push_back(&a3); - in.push_back(&a4); - in.push_back(&a5); - makePath(path, in); -} - -void Path::makePath(const std::string& path, const InArgs& in) { - const char* current = path.c_str(); - const char* end = current + path.length(); - InArgs::const_iterator itInArg = in.begin(); - while (current != end) { - if (*current == '[') { - ++current; - if (*current == '%') - addPathInArg(path, in, itInArg, PathArgument::kindIndex); - else { - ArrayIndex index = 0; - for (; current != end && *current >= '0' && *current <= '9'; ++current) - index = index * 10 + ArrayIndex(*current - '0'); - args_.push_back(index); - } - if (current == end || *current++ != ']') - invalidPath(path, int(current - path.c_str())); - } else if (*current == '%') { - addPathInArg(path, in, itInArg, PathArgument::kindKey); - ++current; - } else if (*current == '.') { - ++current; - } else { - const char* beginName = current; - while (current != end && !strchr("[.", *current)) - ++current; - args_.push_back(std::string(beginName, current)); - } - } -} - -void Path::addPathInArg(const std::string& /*path*/, - const InArgs& in, - InArgs::const_iterator& itInArg, - PathArgument::Kind kind) { - if (itInArg == in.end()) { - // Error: missing argument %d - } else if ((*itInArg)->kind_ != kind) { - // Error: bad argument type - } else { - args_.push_back(**itInArg); - } -} - -void Path::invalidPath(const std::string& /*path*/, int /*location*/) { - // Error: invalid path. -} - -const Value& Path::resolve(const Value& root) const { - const Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray() || !node->isValidIndex(arg.index_)) { - // Error: unable to resolve path (array value expected at position... - } - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) { - // Error: unable to resolve path (object value expected at position...) - } - node = &((*node)[arg.key_]); - if (node == &Value::null) { - // Error: unable to resolve path (object has no member named '' at - // position...) - } - } - } - return *node; -} - -Value Path::resolve(const Value& root, const Value& defaultValue) const { - const Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray() || !node->isValidIndex(arg.index_)) - return defaultValue; - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) - return defaultValue; - node = &((*node)[arg.key_]); - if (node == &Value::null) - return defaultValue; - } - } - return *node; -} - -Value& Path::make(Value& root) const { - Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray()) { - // Error: node is not an array at position ... - } - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) { - // Error: node is not an object at position... - } - node = &((*node)[arg.key_]); - } - } - return *node; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_value.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_writer.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2011 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include -#include "json_tool.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below -#include -#define isfinite _finite -#define snprintf _snprintf -#endif - -#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 -// Disable warning about strdup being deprecated. -#pragma warning(disable : 4996) -#endif - -namespace Json { - -static bool containsControlCharacter(const char* str) { - while (*str) { - if (isControlCharacter(*(str++))) - return true; - } - return false; -} - -std::string valueToString(LargestInt value) { - UIntToStringBuffer buffer; - char* current = buffer + sizeof(buffer); - bool isNegative = value < 0; - if (isNegative) - value = -value; - uintToString(LargestUInt(value), current); - if (isNegative) - *--current = '-'; - assert(current >= buffer); - return current; -} - -std::string valueToString(LargestUInt value) { - UIntToStringBuffer buffer; - char* current = buffer + sizeof(buffer); - uintToString(value, current); - assert(current >= buffer); - return current; -} - -#if defined(JSON_HAS_INT64) - -std::string valueToString(Int value) { - return valueToString(LargestInt(value)); -} - -std::string valueToString(UInt value) { - return valueToString(LargestUInt(value)); -} - -#endif // # if defined(JSON_HAS_INT64) - -std::string valueToString(double value) { - // Allocate a buffer that is more than large enough to store the 16 digits of - // precision requested below. - char buffer[32]; - int len = -1; - -// Print into the buffer. We need not request the alternative representation -// that always has a decimal point because JSON doesn't distingish the -// concepts of reals and integers. -#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with - // visual studio 2005 to - // avoid warning. -#if defined(WINCE) - len = _snprintf(buffer, sizeof(buffer), "%.16g", value); -#else - len = sprintf_s(buffer, sizeof(buffer), "%.16g", value); -#endif -#else - if (isfinite(value)) { - len = snprintf(buffer, sizeof(buffer), "%.16g", value); - } else { - // IEEE standard states that NaN values will not compare to themselves - if (value != value) { - len = snprintf(buffer, sizeof(buffer), "null"); - } else if (value < 0) { - len = snprintf(buffer, sizeof(buffer), "-1e+9999"); - } else { - len = snprintf(buffer, sizeof(buffer), "1e+9999"); - } - // For those, we do not need to call fixNumLoc, but it is fast. - } -#endif - assert(len >= 0); - fixNumericLocale(buffer, buffer + len); - return buffer; -} - -std::string valueToString(bool value) { return value ? "true" : "false"; } - -std::string valueToQuotedString(const char* value) { - if (value == NULL) - return ""; - // Not sure how to handle unicode... - if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && - !containsControlCharacter(value)) - return std::string("\"") + value + "\""; - // We have to walk value and escape any special characters. - // Appending to std::string is not efficient, but this should be rare. - // (Note: forward slashes are *not* rare, but I am not escaping them.) - std::string::size_type maxsize = - strlen(value) * 2 + 3; // allescaped+quotes+NULL - std::string result; - result.reserve(maxsize); // to avoid lots of mallocs - result += "\""; - for (const char* c = value; *c != 0; ++c) { - switch (*c) { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - // case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something. - // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); - result += oss.str(); - } else { - result += *c; - } - break; - } - } - result += "\""; - return result; -} - -// Class Writer -// ////////////////////////////////////////////////////////////////// -Writer::~Writer() {} - -// Class FastWriter -// ////////////////////////////////////////////////////////////////// - -FastWriter::FastWriter() - : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), - omitEndingLineFeed_(false) {} - -void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } - -void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } - -void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } - -std::string FastWriter::write(const Value& root) { - document_ = ""; - writeValue(root); - if (!omitEndingLineFeed_) - document_ += "\n"; - return document_; -} - -void FastWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - if (!dropNullPlaceholders_) - document_ += "null"; - break; - case intValue: - document_ += valueToString(value.asLargestInt()); - break; - case uintValue: - document_ += valueToString(value.asLargestUInt()); - break; - case realValue: - document_ += valueToString(value.asDouble()); - break; - case stringValue: - document_ += valueToQuotedString(value.asCString()); - break; - case booleanValue: - document_ += valueToString(value.asBool()); - break; - case arrayValue: { - document_ += "["; - int size = value.size(); - for (int index = 0; index < size; ++index) { - if (index > 0) - document_ += ","; - writeValue(value[index]); - } - document_ += "]"; - } break; - case objectValue: { - Value::Members members(value.getMemberNames()); - document_ += "{"; - for (Value::Members::iterator it = members.begin(); it != members.end(); - ++it) { - const std::string& name = *it; - if (it != members.begin()) - document_ += ","; - document_ += valueToQuotedString(name.c_str()); - document_ += yamlCompatiblityEnabled_ ? ": " : ":"; - writeValue(value[name]); - } - document_ += "}"; - } break; - } -} - -// Class StyledWriter -// ////////////////////////////////////////////////////////////////// - -StyledWriter::StyledWriter() - : rightMargin_(74), indentSize_(3), addChildValues_() {} - -std::string StyledWriter::write(const Value& root) { - document_ = ""; - addChildValues_ = false; - indentString_ = ""; - writeCommentBeforeValue(root); - writeValue(root); - writeCommentAfterValueOnSameLine(root); - document_ += "\n"; - return document_; -} - -void StyledWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - pushValue("null"); - break; - case intValue: - pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble())); - break; - case stringValue: - pushValue(valueToQuotedString(value.asCString())); - break; - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); - indent(); - Value::Members::iterator it = members.begin(); - for (;;) { - const std::string& name = *it; - const Value& childValue = value[name]; - writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); - document_ += " : "; - writeValue(childValue); - if (++it == members.end()) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - document_ += ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("}"); - } - } break; - } -} - -void StyledWriter::writeArrayValue(const Value& value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isArrayMultiLine = isMultineArray(value); - if (isArrayMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - for (;;) { - const Value& childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - writeIndent(); - writeValue(childValue); - } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - document_ += ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - document_ += "[ "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - document_ += ", "; - document_ += childValues_[index]; - } - document_ += " ]"; - } - } -} - -bool StyledWriter::isMultineArray(const Value& value) { - int size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (int index = 0; index < size && !isMultiLine; ++index) { - const Value& childValue = value[index]; - isMultiLine = - isMultiLine || ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (int index = 0; index < size; ++index) { - writeValue(value[index]); - lineLength += int(childValues_[index].length()); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - -void StyledWriter::pushValue(const std::string& value) { - if (addChildValues_) - childValues_.push_back(value); - else - document_ += value; -} - -void StyledWriter::writeIndent() { - if (!document_.empty()) { - char last = document_[document_.length() - 1]; - if (last == ' ') // already indented - return; - if (last != '\n') // Comments may add new-line - document_ += '\n'; - } - document_ += indentString_; -} - -void StyledWriter::writeWithIndent(const std::string& value) { - writeIndent(); - document_ += value; -} - -void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); } - -void StyledWriter::unindent() { - assert(int(indentString_.size()) >= indentSize_); - indentString_.resize(indentString_.size() - indentSize_); -} - -void StyledWriter::writeCommentBeforeValue(const Value& root) { - if (!root.hasComment(commentBefore)) - return; - - document_ += "\n"; - writeIndent(); - std::string normalizedComment = normalizeEOL(root.getComment(commentBefore)); - std::string::const_iterator iter = normalizedComment.begin(); - while (iter != normalizedComment.end()) { - document_ += *iter; - if (*iter == '\n' && *(iter + 1) == '/') - writeIndent(); - ++iter; - } - - // Comments are stripped of newlines, so add one here - document_ += "\n"; -} - -void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { - if (root.hasComment(commentAfterOnSameLine)) - document_ += " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); - - if (root.hasComment(commentAfter)) { - document_ += "\n"; - document_ += normalizeEOL(root.getComment(commentAfter)); - document_ += "\n"; - } -} - -bool StyledWriter::hasCommentForValue(const Value& value) { - return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); -} - -std::string StyledWriter::normalizeEOL(const std::string& text) { - std::string normalized; - normalized.reserve(text.length()); - const char* begin = text.c_str(); - const char* end = begin + text.length(); - const char* current = begin; - while (current != end) { - char c = *current++; - if (c == '\r') // mac or dos EOL - { - if (*current == '\n') // convert dos EOL - ++current; - normalized += '\n'; - } else // handle unix EOL & other char - normalized += c; - } - return normalized; -} - -// Class StyledStreamWriter -// ////////////////////////////////////////////////////////////////// - -StyledStreamWriter::StyledStreamWriter(std::string indentation) - : document_(NULL), rightMargin_(74), indentation_(indentation), - addChildValues_() {} - -void StyledStreamWriter::write(std::ostream& out, const Value& root) { - document_ = &out; - addChildValues_ = false; - indentString_ = ""; - writeCommentBeforeValue(root); - writeValue(root); - writeCommentAfterValueOnSameLine(root); - *document_ << "\n"; - document_ = NULL; // Forget the stream, for safety. -} - -void StyledStreamWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - pushValue("null"); - break; - case intValue: - pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble())); - break; - case stringValue: - pushValue(valueToQuotedString(value.asCString())); - break; - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); - indent(); - Value::Members::iterator it = members.begin(); - for (;;) { - const std::string& name = *it; - const Value& childValue = value[name]; - writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); - *document_ << " : "; - writeValue(childValue); - if (++it == members.end()) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("}"); - } - } break; - } -} - -void StyledStreamWriter::writeArrayValue(const Value& value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isArrayMultiLine = isMultineArray(value); - if (isArrayMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - for (;;) { - const Value& childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - writeIndent(); - writeValue(childValue); - } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - *document_ << "[ "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - *document_ << ", "; - *document_ << childValues_[index]; - } - *document_ << " ]"; - } - } -} - -bool StyledStreamWriter::isMultineArray(const Value& value) { - int size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (int index = 0; index < size && !isMultiLine; ++index) { - const Value& childValue = value[index]; - isMultiLine = - isMultiLine || ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (int index = 0; index < size; ++index) { - writeValue(value[index]); - lineLength += int(childValues_[index].length()); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - -void StyledStreamWriter::pushValue(const std::string& value) { - if (addChildValues_) - childValues_.push_back(value); - else - *document_ << value; -} - -void StyledStreamWriter::writeIndent() { - /* - Some comments in this method would have been nice. ;-) - - if ( !document_.empty() ) - { - char last = document_[document_.length()-1]; - if ( last == ' ' ) // already indented - return; - if ( last != '\n' ) // Comments may add new-line - *document_ << '\n'; - } - */ - *document_ << '\n' << indentString_; -} - -void StyledStreamWriter::writeWithIndent(const std::string& value) { - writeIndent(); - *document_ << value; -} - -void StyledStreamWriter::indent() { indentString_ += indentation_; } - -void StyledStreamWriter::unindent() { - assert(indentString_.size() >= indentation_.size()); - indentString_.resize(indentString_.size() - indentation_.size()); -} - -void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { - if (!root.hasComment(commentBefore)) - return; - *document_ << normalizeEOL(root.getComment(commentBefore)); - *document_ << "\n"; -} - -void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { - if (root.hasComment(commentAfterOnSameLine)) - *document_ << " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); - - if (root.hasComment(commentAfter)) { - *document_ << "\n"; - *document_ << normalizeEOL(root.getComment(commentAfter)); - *document_ << "\n"; - } -} - -bool StyledStreamWriter::hasCommentForValue(const Value& value) { - return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); -} - -std::string StyledStreamWriter::normalizeEOL(const std::string& text) { - std::string normalized; - normalized.reserve(text.length()); - const char* begin = text.c_str(); - const char* end = begin + text.length(); - const char* current = begin; - while (current != end) { - char c = *current++; - if (c == '\r') // mac or dos EOL - { - if (*current == '\n') // convert dos EOL - ++current; - normalized += '\n'; - } else // handle unix EOL & other char - normalized += c; - } - return normalized; -} - -std::ostream& operator<<(std::ostream& sout, const Value& root) { - Json::StyledStreamWriter writer; - writer.write(sout, root); - return sout; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_writer.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - +/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/). +/// It is intented to be used with #include + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is +released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur + +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. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + + +#include "jsoncpp/json.h" + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_tool.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED +#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +/* This header provides common string manipulation support, such as UTF-8, + * portable conversion from/to string... + * + * It is an internal header that must not be exposed. + */ + +namespace Json { + +/// Converts a unicode code-point to UTF-8. +static inline std::string codePointToUTF8(unsigned int cp) { + std::string result; + + // based on description from http://en.wikipedia.org/wiki/UTF-8 + + if (cp <= 0x7f) { + result.resize(1); + result[0] = static_cast(cp); + } else if (cp <= 0x7FF) { + result.resize(2); + result[1] = static_cast(0x80 | (0x3f & cp)); + result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); + } else if (cp <= 0xFFFF) { + result.resize(3); + result[2] = static_cast(0x80 | (0x3f & cp)); + result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); + result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); + } else if (cp <= 0x10FFFF) { + result.resize(4); + result[3] = static_cast(0x80 | (0x3f & cp)); + result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); + result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); + } + + return result; +} + +/// Returns true if ch is a control character (in range [0,32[). +static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } + +enum { + /// Constant that specify the size of the buffer that must be passed to + /// uintToString. + uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 +}; + +// Defines a char buffer for use with uintToString(). +typedef char UIntToStringBuffer[uintToStringBufferSize]; + +/** Converts an unsigned integer to string. + * @param value Unsigned interger to convert to string + * @param current Input/Output string buffer. + * Must have at least uintToStringBufferSize chars free. + */ +static inline void uintToString(LargestUInt value, char*& current) { + *--current = 0; + do { + *--current = char(value % 10) + '0'; + value /= 10; + } while (value != 0); +} + +/** Change ',' to '.' everywhere in buffer. + * + * We had a sophisticated way, but it did not work in WinCE. + * @see https://github.com/open-source-parsers/jsoncpp/pull/9 + */ +static inline void fixNumericLocale(char* begin, char* end) { + while (begin < end) { + if (*begin == ',') { + *begin = '.'; + } + ++begin; + } +} + +} // namespace Json { + +#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_tool.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_reader.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2011 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include "json_tool.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below +#define snprintf _snprintf +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +namespace Json { + +// Implementation of class Features +// //////////////////////////////// + +Features::Features() + : allowComments_(true), strictRoot_(false), + allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} + +Features Features::all() { return Features(); } + +Features Features::strictMode() { + Features features; + features.allowComments_ = false; + features.strictRoot_ = true; + features.allowDroppedNullPlaceholders_ = false; + features.allowNumericKeys_ = false; + return features; +} + +// Implementation of class Reader +// //////////////////////////////// + +static inline bool in(Reader::Char c, + Reader::Char c1, + Reader::Char c2, + Reader::Char c3, + Reader::Char c4) { + return c == c1 || c == c2 || c == c3 || c == c4; +} + +static inline bool in(Reader::Char c, + Reader::Char c1, + Reader::Char c2, + Reader::Char c3, + Reader::Char c4, + Reader::Char c5) { + return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; +} + +static bool containsNewLine(Reader::Location begin, Reader::Location end) { + for (; begin < end; ++begin) + if (*begin == '\n' || *begin == '\r') + return true; + return false; +} + +// Class Reader +// ////////////////////////////////////////////////////////////////// + +Reader::Reader() + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(Features::all()), + collectComments_() {} + +Reader::Reader(const Features& features) + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(features), collectComments_() { +} + +bool +Reader::parse(const std::string& document, Value& root, bool collectComments) { + document_ = document; + const char* begin = document_.c_str(); + const char* end = begin + document_.length(); + return parse(begin, end, root, collectComments); +} + +bool Reader::parse(std::istream& sin, Value& root, bool collectComments) { + // std::istream_iterator begin(sin); + // std::istream_iterator end; + // Those would allow streamed input from a file, if parse() were a + // template function. + + // Since std::string is reference-counted, this at least does not + // create an extra copy. + std::string doc; + std::getline(sin, doc, (char)EOF); + return parse(doc, root, collectComments); +} + +bool Reader::parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments) { + if (!features_.allowComments_) { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_ = ""; + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + bool successful = readValue(); + Token token; + skipCommentTokens(token); + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { + if (!root.isArray() && !root.isObject()) { + // Set error location to start of doc, ideally should be first token found + // in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( + "A valid JSON document must be either an array or an object value.", + token); + return false; + } + } + return successful; +} + +bool Reader::readValue() { + Token token; + skipCommentTokens(token); + bool successful = true; + + if (collectComments_ && !commentsBefore_.empty()) { + // Remove newline characters at the end of the comments + size_t lastNonNewline = commentsBefore_.find_last_not_of("\r\n"); + if (lastNonNewline != std::string::npos) { + commentsBefore_.erase(lastNonNewline + 1); + } else { + commentsBefore_.clear(); + } + + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_ = ""; + } + + switch (token.type_) { + case tokenObjectBegin: + successful = readObject(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenArrayBegin: + successful = readArray(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: + currentValue() = true; + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + break; + case tokenFalse: + currentValue() = false; + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + break; + case tokenNull: + currentValue() = Value(); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + break; + case tokenArraySeparator: + if (features_.allowDroppedNullPlaceholders_) { + // "Un-read" the current token and mark the current value as a null + // token. + current_--; + currentValue() = Value(); + currentValue().setOffsetStart(current_ - begin_ - 1); + currentValue().setOffsetLimit(current_ - begin_); + break; + } + // Else, fall through... + default: + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return addError("Syntax error: value, object or array expected.", token); + } + + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); + } + + return successful; +} + +void Reader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { + do { + readToken(token); + } while (token.type_ == tokenComment); + } else { + readToken(token); + } +} + +bool Reader::expectToken(TokenType type, Token& token, const char* message) { + readToken(token); + if (token.type_ != type) + return addError(message, token); + return true; +} + +bool Reader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch (c) { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + token.type_ = tokenNumber; + readNumber(); + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if (!ok) + token.type_ = tokenError; + token.end_ = current_; + return true; +} + +void Reader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + ++current_; + else + break; + } +} + +bool Reader::match(Location pattern, int patternLength) { + if (end_ - current_ < patternLength) + return false; + int index = patternLength; + while (index--) + if (current_[index] != pattern[index]) + return false; + current_ += patternLength; + return true; +} + +bool Reader::readComment() { + Location commentBegin = current_ - 1; + Char c = getNextChar(); + bool successful = false; + if (c == '*') + successful = readCStyleComment(); + else if (c == '/') + successful = readCppStyleComment(); + if (!successful) + return false; + + if (collectComments_) { + CommentPlacement placement = commentBefore; + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) + placement = commentAfterOnSameLine; + } + + addComment(commentBegin, current_, placement); + } + return true; +} + +void +Reader::addComment(Location begin, Location end, CommentPlacement placement) { + assert(collectComments_); + if (placement == commentAfterOnSameLine) { + assert(lastValue_ != 0); + lastValue_->setComment(std::string(begin, end), placement); + } else { + commentsBefore_ += std::string(begin, end); + } +} + +bool Reader::readCStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') + break; + } + return getNextChar() == '/'; +} + +bool Reader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '\r' || c == '\n') + break; + } + return true; +} + +void Reader::readNumber() { + while (current_ != end_) { + if (!(*current_ >= '0' && *current_ <= '9') && + !in(*current_, '.', 'e', 'E', '+', '-')) + break; + ++current_; + } +} + +bool Reader::readString() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '"') + break; + } + return c == '"'; +} + +bool Reader::readObject(Token& tokenStart) { + Token tokenName; + std::string name; + currentValue() = Value(objectValue); + currentValue().setOffsetStart(tokenStart.start_ - begin_); + while (readToken(tokenName)) { + bool initialTokenOk = true; + while (tokenName.type_ == tokenComment && initialTokenOk) + initialTokenOk = readToken(tokenName); + if (!initialTokenOk) + break; + if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + return true; + name = ""; + if (tokenName.type_ == tokenString) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { + Value numberName; + if (!decodeNumber(tokenName, numberName)) + return recoverFromError(tokenObjectEnd); + name = numberName.asString(); + } else { + break; + } + + Token colon; + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover( + "Missing ':' after object member name", colon, tokenObjectEnd); + } + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenObjectEnd); + + Token comma; + if (!readToken(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment)) { + return addErrorAndRecover( + "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + } + bool finalizeTokenOk = true; + while (comma.type_ == tokenComment && finalizeTokenOk) + finalizeTokenOk = readToken(comma); + if (comma.type_ == tokenObjectEnd) + return true; + } + return addErrorAndRecover( + "Missing '}' or object member name", tokenName, tokenObjectEnd); +} + +bool Reader::readArray(Token& tokenStart) { + currentValue() = Value(arrayValue); + currentValue().setOffsetStart(tokenStart.start_ - begin_); + skipSpaces(); + if (*current_ == ']') // empty array + { + Token endArray; + readToken(endArray); + return true; + } + int index = 0; + for (;;) { + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenArrayEnd); + + Token token; + // Accept Comment after last item in the array. + ok = readToken(token); + while (token.type_ == tokenComment && ok) { + ok = readToken(token); + } + bool badTokenType = + (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); + if (!ok || badTokenType) { + return addErrorAndRecover( + "Missing ',' or ']' in array declaration", token, tokenArrayEnd); + } + if (token.type_ == tokenArrayEnd) + break; + } + return true; +} + +bool Reader::decodeNumber(Token& token) { + Value decoded; + if (!decodeNumber(token, decoded)) + return false; + currentValue() = decoded; + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeNumber(Token& token, Value& decoded) { + bool isDouble = false; + for (Location inspect = token.start_; inspect != token.end_; ++inspect) { + isDouble = isDouble || in(*inspect, '.', 'e', 'E', '+') || + (*inspect == '-' && inspect != token.start_); + } + if (isDouble) + return decodeDouble(token, decoded); + // Attempts to parse the number as an integer. If the number is + // larger than the maximum supported value of an integer then + // we decode the number as a double. + Location current = token.start_; + bool isNegative = *current == '-'; + if (isNegative) + ++current; + Value::LargestUInt maxIntegerValue = + isNegative ? Value::LargestUInt(-Value::minLargestInt) + : Value::maxLargestUInt; + Value::LargestUInt threshold = maxIntegerValue / 10; + Value::LargestUInt value = 0; + while (current < token.end_) { + Char c = *current++; + if (c < '0' || c > '9') + return addError("'" + std::string(token.start_, token.end_) + + "' is not a number.", + token); + Value::UInt digit(c - '0'); + if (value >= threshold) { + // We've hit or exceeded the max value divided by 10 (rounded down). If + // a) we've only just touched the limit, b) this is the last digit, and + // c) it's small enough to fit in that rounding delta, we're okay. + // Otherwise treat this number as a double to avoid overflow. + if (value > threshold || current != token.end_ || + digit > maxIntegerValue % 10) { + return decodeDouble(token, decoded); + } + } + value = value * 10 + digit; + } + if (isNegative) + decoded = -Value::LargestInt(value); + else if (value <= Value::LargestUInt(Value::maxInt)) + decoded = Value::LargestInt(value); + else + decoded = value; + return true; +} + +bool Reader::decodeDouble(Token& token) { + Value decoded; + if (!decodeDouble(token, decoded)) + return false; + currentValue() = decoded; + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeDouble(Token& token, Value& decoded) { + double value = 0; + const int bufferSize = 32; + int count; + int length = int(token.end_ - token.start_); + + // Sanity check to avoid buffer overflow exploits. + if (length < 0) { + return addError("Unable to parse token length", token); + } + + // Avoid using a string constant for the format control string given to + // sscanf, as this can cause hard to debug crashes on OS X. See here for more + // info: + // + // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html + char format[] = "%lf"; + + if (length <= bufferSize) { + Char buffer[bufferSize + 1]; + memcpy(buffer, token.start_, length); + buffer[length] = 0; + count = sscanf(buffer, format, &value); + } else { + std::string buffer(token.start_, token.end_); + count = sscanf(buffer.c_str(), format, &value); + } + + if (count != 1) + return addError("'" + std::string(token.start_, token.end_) + + "' is not a number.", + token); + decoded = value; + return true; +} + +bool Reader::decodeString(Token& token) { + std::string decoded; + if (!decodeString(token, decoded)) + return false; + currentValue() = decoded; + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeString(Token& token, std::string& decoded) { + decoded.reserve(token.end_ - token.start_ - 2); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + while (current != end) { + Char c = *current++; + if (c == '"') + break; + else if (c == '\\') { + if (current == end) + return addError("Empty escape sequence in string", token, current); + Char escape = *current++; + switch (escape) { + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); + } + } else { + decoded += c; + } + } + return true; +} + +bool Reader::decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) { + // surrogate pairs + if (end - current < 6) + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, + current); + unsigned int surrogatePair; + if (*(current++) == '\\' && *(current++) == 'u') { + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } else + return false; + } else + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, + current); + } + return true; +} + +bool Reader::decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + if (end - current < 4) + return addError( + "Bad unicode escape sequence in string: four digits expected.", + token, + current); + unicode = 0; + for (int index = 0; index < 4; ++index) { + Char c = *current++; + unicode *= 16; + if (c >= '0' && c <= '9') + unicode += c - '0'; + else if (c >= 'a' && c <= 'f') + unicode += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + unicode += c - 'A' + 10; + else + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, + current); + } + return true; +} + +bool +Reader::addError(const std::string& message, Token& token, Location extra) { + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back(info); + return false; +} + +bool Reader::recoverFromError(TokenType skipUntilToken) { + int errorCount = int(errors_.size()); + Token skip; + for (;;) { + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery + if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) + break; + } + errors_.resize(errorCount); + return false; +} + +bool Reader::addErrorAndRecover(const std::string& message, + Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); +} + +Value& Reader::currentValue() { return *(nodes_.top()); } + +Reader::Char Reader::getNextChar() { + if (current_ == end_) + return 0; + return *current_++; +} + +void Reader::getLocationLineAndColumn(Location location, + int& line, + int& column) const { + Location current = begin_; + Location lastLineStart = current; + line = 0; + while (current < location && current != end_) { + Char c = *current++; + if (c == '\r') { + if (*current == '\n') + ++current; + lastLineStart = current; + ++line; + } else if (c == '\n') { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + +std::string Reader::getLocationLineAndColumn(Location location) const { + int line, column; + getLocationLineAndColumn(location, line, column); + char buffer[18 + 16 + 16 + 1]; +#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) +#if defined(WINCE) + _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); +#else + sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column); +#endif +#else + snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); +#endif + return buffer; +} + +// Deprecated. Preserved for backward compatibility +std::string Reader::getFormatedErrorMessages() const { + return getFormattedErrorMessages(); +} + +std::string Reader::getFormattedErrorMessages() const { + std::string formattedMessage; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { + const ErrorInfo& error = *itError; + formattedMessage += + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if (error.extra_) + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; + } + return formattedMessage; +} + +std::vector Reader::getStructuredErrors() const { + std::vector allErrors; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { + const ErrorInfo& error = *itError; + Reader::StructuredError structured; + structured.offset_start = error.token_.start_ - begin_; + structured.offset_limit = error.token_.end_ - begin_; + structured.message = error.message_; + allErrors.push_back(structured); + } + return allErrors; +} + +std::istream& operator>>(std::istream& sin, Value& root) { + Json::Reader reader; + bool ok = reader.parse(sin, root, true); + if (!ok) { + fprintf(stderr, + "Error from reader: %s", + reader.getFormattedErrorMessages().c_str()); + + JSON_FAIL_MESSAGE("reader error"); + } + return sin; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_reader.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_batchallocator.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED +#define JSONCPP_BATCHALLOCATOR_H_INCLUDED + +#include +#include + +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + +namespace Json { + +/* Fast memory allocator. + * + * This memory allocator allocates memory for a batch of object (specified by + * the page size, the number of object in each page). + * + * It does not allow the destruction of a single object. All the allocated + * objects can be destroyed at once. The memory can be either released or reused + * for future allocation. + * + * The in-place new operator must be used to construct the object using the + * pointer returned by allocate. + */ +template +class BatchAllocator { +public: + BatchAllocator(unsigned int objectsPerPage = 255) + : freeHead_(0), objectsPerPage_(objectsPerPage) { + // printf( "Size: %d => %s\n", sizeof(AllocatedType), + // typeid(AllocatedType).name() ); + assert(sizeof(AllocatedType) * objectPerAllocation >= + sizeof(AllocatedType*)); // We must be able to store a slist in the + // object free space. + assert(objectsPerPage >= 16); + batches_ = allocateBatch(0); // allocated a dummy page + currentBatch_ = batches_; + } + + ~BatchAllocator() { + for (BatchInfo* batch = batches_; batch;) { + BatchInfo* nextBatch = batch->next_; + free(batch); + batch = nextBatch; + } + } + + /// allocate space for an array of objectPerAllocation object. + /// @warning it is the responsability of the caller to call objects + /// constructors. + AllocatedType* allocate() { + if (freeHead_) // returns node from free list. + { + AllocatedType* object = freeHead_; + freeHead_ = *(AllocatedType**)object; + return object; + } + if (currentBatch_->used_ == currentBatch_->end_) { + currentBatch_ = currentBatch_->next_; + while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_) + currentBatch_ = currentBatch_->next_; + + if (!currentBatch_) // no free batch found, allocate a new one + { + currentBatch_ = allocateBatch(objectsPerPage_); + currentBatch_->next_ = batches_; // insert at the head of the list + batches_ = currentBatch_; + } + } + AllocatedType* allocated = currentBatch_->used_; + currentBatch_->used_ += objectPerAllocation; + return allocated; + } + + /// Release the object. + /// @warning it is the responsability of the caller to actually destruct the + /// object. + void release(AllocatedType* object) { + assert(object != 0); + *(AllocatedType**)object = freeHead_; + freeHead_ = object; + } + +private: + struct BatchInfo { + BatchInfo* next_; + AllocatedType* used_; + AllocatedType* end_; + AllocatedType buffer_[objectPerAllocation]; + }; + + // disabled copy constructor and assignement operator. + BatchAllocator(const BatchAllocator&); + void operator=(const BatchAllocator&); + + static BatchInfo* allocateBatch(unsigned int objectsPerPage) { + const unsigned int mallocSize = + sizeof(BatchInfo) - sizeof(AllocatedType) * objectPerAllocation + + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; + BatchInfo* batch = static_cast(malloc(mallocSize)); + batch->next_ = 0; + batch->used_ = batch->buffer_; + batch->end_ = batch->buffer_ + objectsPerPage; + return batch; + } + + BatchInfo* batches_; + BatchInfo* currentBatch_; + /// Head of a single linked list within the allocated space of freeed object + AllocatedType* freeHead_; + unsigned int objectsPerPage_; +}; + +} // namespace Json + +#endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION + +#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_batchallocator.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_valueiterator.inl +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +// included by json_value.cpp + +namespace Json { + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIteratorBase +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIteratorBase::ValueIteratorBase() +#ifndef JSON_VALUE_USE_INTERNAL_MAP + : current_(), isNull_(true) { +} +#else + : isArray_(true), isNull_(true) { + iterator_.array_ = ValueInternalArray::IteratorState(); +} +#endif + +#ifndef JSON_VALUE_USE_INTERNAL_MAP +ValueIteratorBase::ValueIteratorBase( + const Value::ObjectValues::iterator& current) + : current_(current), isNull_(false) {} +#else +ValueIteratorBase::ValueIteratorBase( + const ValueInternalArray::IteratorState& state) + : isArray_(true) { + iterator_.array_ = state; +} + +ValueIteratorBase::ValueIteratorBase( + const ValueInternalMap::IteratorState& state) + : isArray_(false) { + iterator_.map_ = state; +} +#endif + +Value& ValueIteratorBase::deref() const { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + return current_->second; +#else + if (isArray_) + return ValueInternalArray::dereference(iterator_.array_); + return ValueInternalMap::value(iterator_.map_); +#endif +} + +void ValueIteratorBase::increment() { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + ++current_; +#else + if (isArray_) + ValueInternalArray::increment(iterator_.array_); + ValueInternalMap::increment(iterator_.map_); +#endif +} + +void ValueIteratorBase::decrement() { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + --current_; +#else + if (isArray_) + ValueInternalArray::decrement(iterator_.array_); + ValueInternalMap::decrement(iterator_.map_); +#endif +} + +ValueIteratorBase::difference_type +ValueIteratorBase::computeDistance(const SelfType& other) const { +#ifndef JSON_VALUE_USE_INTERNAL_MAP +#ifdef JSON_USE_CPPTL_SMALLMAP + return current_ - other.current_; +#else + // Iterator for null value are initialized using the default + // constructor, which initialize current_ to the default + // std::map::iterator. As begin() and end() are two instance + // of the default std::map::iterator, they can not be compared. + // To allow this, we handle this comparison specifically. + if (isNull_ && other.isNull_) { + return 0; + } + + // Usage of std::distance is not portable (does not compile with Sun Studio 12 + // RogueWave STL, + // which is the one used by default). + // Using a portable hand-made version for non random iterator instead: + // return difference_type( std::distance( current_, other.current_ ) ); + difference_type myDistance = 0; + for (Value::ObjectValues::iterator it = current_; it != other.current_; + ++it) { + ++myDistance; + } + return myDistance; +#endif +#else + if (isArray_) + return ValueInternalArray::distance(iterator_.array_, + other.iterator_.array_); + return ValueInternalMap::distance(iterator_.map_, other.iterator_.map_); +#endif +} + +bool ValueIteratorBase::isEqual(const SelfType& other) const { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + if (isNull_) { + return other.isNull_; + } + return current_ == other.current_; +#else + if (isArray_) + return ValueInternalArray::equals(iterator_.array_, other.iterator_.array_); + return ValueInternalMap::equals(iterator_.map_, other.iterator_.map_); +#endif +} + +void ValueIteratorBase::copy(const SelfType& other) { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + current_ = other.current_; + isNull_ = other.isNull_; +#else + if (isArray_) + iterator_.array_ = other.iterator_.array_; + iterator_.map_ = other.iterator_.map_; +#endif +} + +Value ValueIteratorBase::key() const { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + const Value::CZString czstring = (*current_).first; + if (czstring.c_str()) { + if (czstring.isStaticString()) + return Value(StaticString(czstring.c_str())); + return Value(czstring.c_str()); + } + return Value(czstring.index()); +#else + if (isArray_) + return Value(ValueInternalArray::indexOf(iterator_.array_)); + bool isStatic; + const char* memberName = ValueInternalMap::key(iterator_.map_, isStatic); + if (isStatic) + return Value(StaticString(memberName)); + return Value(memberName); +#endif +} + +UInt ValueIteratorBase::index() const { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + const Value::CZString czstring = (*current_).first; + if (!czstring.c_str()) + return czstring.index(); + return Value::UInt(-1); +#else + if (isArray_) + return Value::UInt(ValueInternalArray::indexOf(iterator_.array_)); + return Value::UInt(-1); +#endif +} + +const char* ValueIteratorBase::memberName() const { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + const char* name = (*current_).first.c_str(); + return name ? name : ""; +#else + if (!isArray_) + return ValueInternalMap::key(iterator_.map_); + return ""; +#endif +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueConstIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueConstIterator::ValueConstIterator() {} + +#ifndef JSON_VALUE_USE_INTERNAL_MAP +ValueConstIterator::ValueConstIterator( + const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} +#else +ValueConstIterator::ValueConstIterator( + const ValueInternalArray::IteratorState& state) + : ValueIteratorBase(state) {} + +ValueConstIterator::ValueConstIterator( + const ValueInternalMap::IteratorState& state) + : ValueIteratorBase(state) {} +#endif + +ValueConstIterator& ValueConstIterator:: +operator=(const ValueIteratorBase& other) { + copy(other); + return *this; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIterator::ValueIterator() {} + +#ifndef JSON_VALUE_USE_INTERNAL_MAP +ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} +#else +ValueIterator::ValueIterator(const ValueInternalArray::IteratorState& state) + : ValueIteratorBase(state) {} + +ValueIterator::ValueIterator(const ValueInternalMap::IteratorState& state) + : ValueIteratorBase(state) {} +#endif + +ValueIterator::ValueIterator(const ValueConstIterator& other) + : ValueIteratorBase(other) {} + +ValueIterator::ValueIterator(const ValueIterator& other) + : ValueIteratorBase(other) {} + +ValueIterator& ValueIterator::operator=(const SelfType& other) { + copy(other); + return *this; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_valueiterator.inl +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_value.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2011 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR +#include "json_batchallocator.h" +#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#ifdef JSON_USE_CPPTL +#include +#endif +#include // size_t + +#define JSON_ASSERT_UNREACHABLE assert(false) + +namespace Json { + +// This is a walkaround to avoid the static initialization of Value::null. +// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of +// 8 (instead of 4) as a bit of future-proofing. +#if defined(__ARMEL__) +#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) +#else +#define ALIGNAS(byte_alignment) +#endif +static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; +const unsigned char& kNullRef = kNull[0]; +const Value& Value::null = reinterpret_cast(kNullRef); + +const Int Value::minInt = Int(~(UInt(-1) / 2)); +const Int Value::maxInt = Int(UInt(-1) / 2); +const UInt Value::maxUInt = UInt(-1); +#if defined(JSON_HAS_INT64) +const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); +const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); +const UInt64 Value::maxUInt64 = UInt64(-1); +// The constant is hard-coded because some compiler have trouble +// converting Value::maxUInt64 to a double correctly (AIX/xlC). +// Assumes that UInt64 is a 64 bits integer. +static const double maxUInt64AsDouble = 18446744073709551615.0; +#endif // defined(JSON_HAS_INT64) +const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); +const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); +const LargestUInt Value::maxLargestUInt = LargestUInt(-1); + +/// Unknown size marker +static const unsigned int unknown = (unsigned)-1; + +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +template +static inline bool InRange(double d, T min, U max) { + return d >= min && d <= max; +} +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +static inline double integerToDouble(Json::UInt64 value) { + return static_cast(Int64(value / 2)) * 2.0 + Int64(value & 1); +} + +template static inline double integerToDouble(T value) { + return static_cast(value); +} + +template +static inline bool InRange(double d, T min, U max) { + return d >= integerToDouble(min) && d <= integerToDouble(max); +} +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + +/** Duplicates the specified string value. + * @param value Pointer to the string to duplicate. Must be zero-terminated if + * length is "unknown". + * @param length Length of the value. if equals to unknown, then it will be + * computed using strlen(value). + * @return Pointer on the duplicate instance of string. + */ +static inline char* duplicateStringValue(const char* value, + unsigned int length = unknown) { + if (length == unknown) + length = (unsigned int)strlen(value); + + // Avoid an integer overflow in the call to malloc below by limiting length + // to a sane value. + if (length >= (unsigned)Value::maxInt) + length = Value::maxInt - 1; + + char* newString = static_cast(malloc(length + 1)); + JSON_ASSERT_MESSAGE(newString != 0, + "in Json::Value::duplicateStringValue(): " + "Failed to allocate string value buffer"); + memcpy(newString, value, length); + newString[length] = 0; + return newString; +} + +/** Free the string duplicated by duplicateStringValue(). + */ +static inline void releaseStringValue(char* value) { free(value); } + +} // namespace Json + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ValueInternals... +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +#if !defined(JSON_IS_AMALGAMATION) +#ifdef JSON_VALUE_USE_INTERNAL_MAP +#include "json_internalarray.inl" +#include "json_internalmap.inl" +#endif // JSON_VALUE_USE_INTERNAL_MAP + +#include "json_valueiterator.inl" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CommentInfo +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +Value::CommentInfo::CommentInfo() : comment_(0) {} + +Value::CommentInfo::~CommentInfo() { + if (comment_) + releaseStringValue(comment_); +} + +void Value::CommentInfo::setComment(const char* text) { + if (comment_) + releaseStringValue(comment_); + JSON_ASSERT(text != 0); + JSON_ASSERT_MESSAGE( + text[0] == '\0' || text[0] == '/', + "in Json::Value::setComment(): Comments must start with /"); + // It seems that /**/ style comments are acceptable as well. + comment_ = duplicateStringValue(text); +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CZString +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +#ifndef JSON_VALUE_USE_INTERNAL_MAP + +// Notes: index_ indicates if the string was allocated when +// a string is stored. + +Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {} + +Value::CZString::CZString(const char* cstr, DuplicationPolicy allocate) + : cstr_(allocate == duplicate ? duplicateStringValue(cstr) : cstr), + index_(allocate) {} + +Value::CZString::CZString(const CZString& other) + : cstr_(other.index_ != noDuplication && other.cstr_ != 0 + ? duplicateStringValue(other.cstr_) + : other.cstr_), + index_(other.cstr_ + ? (other.index_ == noDuplication ? noDuplication : duplicate) + : other.index_) {} + +Value::CZString::~CZString() { + if (cstr_ && index_ == duplicate) + releaseStringValue(const_cast(cstr_)); +} + +void Value::CZString::swap(CZString& other) { + std::swap(cstr_, other.cstr_); + std::swap(index_, other.index_); +} + +Value::CZString& Value::CZString::operator=(CZString other) { + swap(other); + return *this; +} + +bool Value::CZString::operator<(const CZString& other) const { + if (cstr_) + return strcmp(cstr_, other.cstr_) < 0; + return index_ < other.index_; +} + +bool Value::CZString::operator==(const CZString& other) const { + if (cstr_) + return strcmp(cstr_, other.cstr_) == 0; + return index_ == other.index_; +} + +ArrayIndex Value::CZString::index() const { return index_; } + +const char* Value::CZString::c_str() const { return cstr_; } + +bool Value::CZString::isStaticString() const { return index_ == noDuplication; } + +#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::Value +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +/*! \internal Default constructor initialization must be equivalent to: + * memset( this, 0, sizeof(Value) ) + * This optimization is used in ValueInternalMap fast allocator. + */ +Value::Value(ValueType type) + : type_(type), allocated_(false) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(0), limit_(0) { + switch (type) { + case nullValue: + break; + case intValue: + case uintValue: + value_.int_ = 0; + break; + case realValue: + value_.real_ = 0.0; + break; + case stringValue: + value_.string_ = 0; + break; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(); + break; +#else + case arrayValue: + value_.array_ = arrayAllocator()->newArray(); + break; + case objectValue: + value_.map_ = mapAllocator()->newMap(); + break; +#endif + case booleanValue: + value_.bool_ = false; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +Value::Value(UInt value) + : type_(uintValue), allocated_(false) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(0), limit_(0) { + value_.uint_ = value; +} + +Value::Value(Int value) + : type_(intValue), allocated_(false) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(0), limit_(0) { + value_.int_ = value; +} + +#if defined(JSON_HAS_INT64) +Value::Value(Int64 value) + : type_(intValue), allocated_(false) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(0), limit_(0) { + value_.int_ = value; +} + +Value::Value(UInt64 value) + : type_(uintValue), allocated_(false) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(0), limit_(0) { + value_.uint_ = value; +} +#endif // defined(JSON_HAS_INT64) + +Value::Value(double value) + : type_(realValue), allocated_(false) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(0), limit_(0) { + value_.real_ = value; +} + +Value::Value(const char* value) + : type_(stringValue), allocated_(true) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(0), limit_(0) { + value_.string_ = duplicateStringValue(value); +} + +Value::Value(const char* beginValue, const char* endValue) + : type_(stringValue), allocated_(true) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(0), limit_(0) { + value_.string_ = + duplicateStringValue(beginValue, (unsigned int)(endValue - beginValue)); +} + +Value::Value(const std::string& value) + : type_(stringValue), allocated_(true) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(0), limit_(0) { + value_.string_ = + duplicateStringValue(value.c_str(), (unsigned int)value.length()); +} + +Value::Value(const StaticString& value) + : type_(stringValue), allocated_(false) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(0), limit_(0) { + value_.string_ = const_cast(value.c_str()); +} + +#ifdef JSON_USE_CPPTL +Value::Value(const CppTL::ConstString& value) + : type_(stringValue), allocated_(true) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(0), limit_(0) { + value_.string_ = duplicateStringValue(value, value.length()); +} +#endif + +Value::Value(bool value) + : type_(booleanValue), allocated_(false) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(0), limit_(0) { + value_.bool_ = value; +} + +Value::Value(const Value& other) + : type_(other.type_), allocated_(false) +#ifdef JSON_VALUE_USE_INTERNAL_MAP + , + itemIsUsed_(0) +#endif + , + comments_(0), start_(other.start_), limit_(other.limit_) { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if (other.value_.string_) { + value_.string_ = duplicateStringValue(other.value_.string_); + allocated_ = true; + } else { + value_.string_ = 0; + allocated_ = false; + } + break; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(*other.value_.map_); + break; +#else + case arrayValue: + value_.array_ = arrayAllocator()->newArrayCopy(*other.value_.array_); + break; + case objectValue: + value_.map_ = mapAllocator()->newMapCopy(*other.value_.map_); + break; +#endif + default: + JSON_ASSERT_UNREACHABLE; + } + if (other.comments_) { + comments_ = new CommentInfo[numberOfCommentPlacement]; + for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { + const CommentInfo& otherComment = other.comments_[comment]; + if (otherComment.comment_) + comments_[comment].setComment(otherComment.comment_); + } + } +} + +Value::~Value() { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if (allocated_) + releaseStringValue(value_.string_); + break; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + delete value_.map_; + break; +#else + case arrayValue: + arrayAllocator()->destructArray(value_.array_); + break; + case objectValue: + mapAllocator()->destructMap(value_.map_); + break; +#endif + default: + JSON_ASSERT_UNREACHABLE; + } + + if (comments_) + delete[] comments_; +} + +Value& Value::operator=(Value other) { + swap(other); + return *this; +} + +void Value::swap(Value& other) { + ValueType temp = type_; + type_ = other.type_; + other.type_ = temp; + std::swap(value_, other.value_); + int temp2 = allocated_; + allocated_ = other.allocated_; + other.allocated_ = temp2; + std::swap(start_, other.start_); + std::swap(limit_, other.limit_); +} + +ValueType Value::type() const { return type_; } + +int Value::compare(const Value& other) const { + if (*this < other) + return -1; + if (*this > other) + return 1; + return 0; +} + +bool Value::operator<(const Value& other) const { + int typeDelta = type_ - other.type_; + if (typeDelta) + return typeDelta < 0 ? true : false; + switch (type_) { + case nullValue: + return false; + case intValue: + return value_.int_ < other.value_.int_; + case uintValue: + return value_.uint_ < other.value_.uint_; + case realValue: + return value_.real_ < other.value_.real_; + case booleanValue: + return value_.bool_ < other.value_.bool_; + case stringValue: + return (value_.string_ == 0 && other.value_.string_) || + (other.value_.string_ && value_.string_ && + strcmp(value_.string_, other.value_.string_) < 0); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: { + int delta = int(value_.map_->size() - other.value_.map_->size()); + if (delta) + return delta < 0; + return (*value_.map_) < (*other.value_.map_); + } +#else + case arrayValue: + return value_.array_->compare(*(other.value_.array_)) < 0; + case objectValue: + return value_.map_->compare(*(other.value_.map_)) < 0; +#endif + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator<=(const Value& other) const { return !(other < *this); } + +bool Value::operator>=(const Value& other) const { return !(*this < other); } + +bool Value::operator>(const Value& other) const { return other < *this; } + +bool Value::operator==(const Value& other) const { + // if ( type_ != other.type_ ) + // GCC 2.95.3 says: + // attempt to take address of bit-field structure member `Json::Value::type_' + // Beats me, but a temp solves the problem. + int temp = other.type_; + if (type_ != temp) + return false; + switch (type_) { + case nullValue: + return true; + case intValue: + return value_.int_ == other.value_.int_; + case uintValue: + return value_.uint_ == other.value_.uint_; + case realValue: + return value_.real_ == other.value_.real_; + case booleanValue: + return value_.bool_ == other.value_.bool_; + case stringValue: + return (value_.string_ == other.value_.string_) || + (other.value_.string_ && value_.string_ && + strcmp(value_.string_, other.value_.string_) == 0); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + return value_.map_->size() == other.value_.map_->size() && + (*value_.map_) == (*other.value_.map_); +#else + case arrayValue: + return value_.array_->compare(*(other.value_.array_)) == 0; + case objectValue: + return value_.map_->compare(*(other.value_.map_)) == 0; +#endif + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator!=(const Value& other) const { return !(*this == other); } + +const char* Value::asCString() const { + JSON_ASSERT_MESSAGE(type_ == stringValue, + "in Json::Value::asCString(): requires stringValue"); + return value_.string_; +} + +std::string Value::asString() const { + switch (type_) { + case nullValue: + return ""; + case stringValue: + return value_.string_ ? value_.string_ : ""; + case booleanValue: + return value_.bool_ ? "true" : "false"; + case intValue: + return valueToString(value_.int_); + case uintValue: + return valueToString(value_.uint_); + case realValue: + return valueToString(value_.real_); + default: + JSON_FAIL_MESSAGE("Type is not convertible to string"); + } +} + +#ifdef JSON_USE_CPPTL +CppTL::ConstString Value::asConstString() const { + return CppTL::ConstString(asString().c_str()); +} +#endif + +Value::Int Value::asInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); + return Int(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); + return Int(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), + "double out of Int range"); + return Int(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int."); +} + +Value::UInt Value::asUInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); + return UInt(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); + return UInt(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), + "double out of UInt range"); + return UInt(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt."); +} + +#if defined(JSON_HAS_INT64) + +Value::Int64 Value::asInt64() const { + switch (type_) { + case intValue: + return Int64(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); + return Int64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), + "double out of Int64 range"); + return Int64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int64."); +} + +Value::UInt64 Value::asUInt64() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); + return UInt64(value_.int_); + case uintValue: + return UInt64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), + "double out of UInt64 range"); + return UInt64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); +} +#endif // if defined(JSON_HAS_INT64) + +LargestInt Value::asLargestInt() const { +#if defined(JSON_NO_INT64) + return asInt(); +#else + return asInt64(); +#endif +} + +LargestUInt Value::asLargestUInt() const { +#if defined(JSON_NO_INT64) + return asUInt(); +#else + return asUInt64(); +#endif +} + +double Value::asDouble() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return integerToDouble(value_.uint_); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return value_.real_; + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0 : 0.0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to double."); +} + +float Value::asFloat() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return integerToDouble(value_.uint_); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return static_cast(value_.real_); + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0f : 0.0f; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to float."); +} + +bool Value::asBool() const { + switch (type_) { + case booleanValue: + return value_.bool_; + case nullValue: + return false; + case intValue: + return value_.int_ ? true : false; + case uintValue: + return value_.uint_ ? true : false; + case realValue: + return value_.real_ ? true : false; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to bool."); +} + +bool Value::isConvertibleTo(ValueType other) const { + switch (other) { + case nullValue: + return (isNumeric() && asDouble() == 0.0) || + (type_ == booleanValue && value_.bool_ == false) || + (type_ == stringValue && asString() == "") || + (type_ == arrayValue && value_.map_->size() == 0) || + (type_ == objectValue && value_.map_->size() == 0) || + type_ == nullValue; + case intValue: + return isInt() || + (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || + type_ == booleanValue || type_ == nullValue; + case uintValue: + return isUInt() || + (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || + type_ == booleanValue || type_ == nullValue; + case realValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case booleanValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case stringValue: + return isNumeric() || type_ == booleanValue || type_ == stringValue || + type_ == nullValue; + case arrayValue: + return type_ == arrayValue || type_ == nullValue; + case objectValue: + return type_ == objectValue || type_ == nullValue; + } + JSON_ASSERT_UNREACHABLE; + return false; +} + +/// Number of values in array or object +ArrayIndex Value::size() const { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + case stringValue: + return 0; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: // size of the array is highest index + 1 + if (!value_.map_->empty()) { + ObjectValues::const_iterator itLast = value_.map_->end(); + --itLast; + return (*itLast).first.index() + 1; + } + return 0; + case objectValue: + return ArrayIndex(value_.map_->size()); +#else + case arrayValue: + return Int(value_.array_->size()); + case objectValue: + return Int(value_.map_->size()); +#endif + } + JSON_ASSERT_UNREACHABLE; + return 0; // unreachable; +} + +bool Value::empty() const { + if (isNull() || isArray() || isObject()) + return size() == 0u; + else + return false; +} + +bool Value::operator!() const { return isNull(); } + +void Value::clear() { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || + type_ == objectValue, + "in Json::Value::clear(): requires complex value"); + start_ = 0; + limit_ = 0; + switch (type_) { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + value_.map_->clear(); + break; +#else + case arrayValue: + value_.array_->clear(); + break; + case objectValue: + value_.map_->clear(); + break; +#endif + default: + break; + } +} + +void Value::resize(ArrayIndex newSize) { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, + "in Json::Value::resize(): requires arrayValue"); + if (type_ == nullValue) + *this = Value(arrayValue); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + ArrayIndex oldSize = size(); + if (newSize == 0) + clear(); + else if (newSize > oldSize) + (*this)[newSize - 1]; + else { + for (ArrayIndex index = newSize; index < oldSize; ++index) { + value_.map_->erase(index); + } + assert(size() == newSize); + } +#else + value_.array_->resize(newSize); +#endif +} + +Value& Value::operator[](ArrayIndex index) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex): requires arrayValue"); + if (type_ == nullValue) + *this = Value(arrayValue); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString key(index); + ObjectValues::iterator it = value_.map_->lower_bound(key); + if (it != value_.map_->end() && (*it).first == key) + return (*it).second; + + ObjectValues::value_type defaultValue(key, null); + it = value_.map_->insert(it, defaultValue); + return (*it).second; +#else + return value_.array_->resolveReference(index); +#endif +} + +Value& Value::operator[](int index) { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index): index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +const Value& Value::operator[](ArrayIndex index) const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); + if (type_ == nullValue) + return null; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString key(index); + ObjectValues::const_iterator it = value_.map_->find(key); + if (it == value_.map_->end()) + return null; + return (*it).second; +#else + Value* value = value_.array_->find(index); + return value ? *value : null; +#endif +} + +const Value& Value::operator[](int index) const { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index) const: index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +Value& Value::operator[](const char* key) { + return resolveReference(key, false); +} + +Value& Value::resolveReference(const char* key, bool isStatic) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::resolveReference(): requires objectValue"); + if (type_ == nullValue) + *this = Value(objectValue); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString actualKey( + key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy); + ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) + return (*it).second; + + ObjectValues::value_type defaultValue(actualKey, null); + it = value_.map_->insert(it, defaultValue); + Value& value = (*it).second; + return value; +#else + return value_.map_->resolveReference(key, isStatic); +#endif +} + +Value Value::get(ArrayIndex index, const Value& defaultValue) const { + const Value* value = &((*this)[index]); + return value == &null ? defaultValue : *value; +} + +bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } + +const Value& Value::operator[](const char* key) const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::operator[](char const*)const: requires objectValue"); + if (type_ == nullValue) + return null; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString actualKey(key, CZString::noDuplication); + ObjectValues::const_iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return null; + return (*it).second; +#else + const Value* value = value_.map_->find(key); + return value ? *value : null; +#endif +} + +Value& Value::operator[](const std::string& key) { + return (*this)[key.c_str()]; +} + +const Value& Value::operator[](const std::string& key) const { + return (*this)[key.c_str()]; +} + +Value& Value::operator[](const StaticString& key) { + return resolveReference(key, true); +} + +#ifdef JSON_USE_CPPTL +Value& Value::operator[](const CppTL::ConstString& key) { + return (*this)[key.c_str()]; +} + +const Value& Value::operator[](const CppTL::ConstString& key) const { + return (*this)[key.c_str()]; +} +#endif + +Value& Value::append(const Value& value) { return (*this)[size()] = value; } + +Value Value::get(const char* key, const Value& defaultValue) const { + const Value* value = &((*this)[key]); + return value == &null ? defaultValue : *value; +} + +Value Value::get(const std::string& key, const Value& defaultValue) const { + return get(key.c_str(), defaultValue); +} + +Value Value::removeMember(const char* key) { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, + "in Json::Value::removeMember(): requires objectValue"); + if (type_ == nullValue) + return null; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString actualKey(key, CZString::noDuplication); + ObjectValues::iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return null; + Value old(it->second); + value_.map_->erase(it); + return old; +#else + Value* value = value_.map_->find(key); + if (value) { + Value old(*value); + value_.map_.remove(key); + return old; + } else { + return null; + } +#endif +} + +Value Value::removeMember(const std::string& key) { + return removeMember(key.c_str()); +} + +#ifdef JSON_USE_CPPTL +Value Value::get(const CppTL::ConstString& key, + const Value& defaultValue) const { + return get(key.c_str(), defaultValue); +} +#endif + +bool Value::isMember(const char* key) const { + const Value* value = &((*this)[key]); + return value != &null; +} + +bool Value::isMember(const std::string& key) const { + return isMember(key.c_str()); +} + +#ifdef JSON_USE_CPPTL +bool Value::isMember(const CppTL::ConstString& key) const { + return isMember(key.c_str()); +} +#endif + +Value::Members Value::getMemberNames() const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::getMemberNames(), value must be objectValue"); + if (type_ == nullValue) + return Value::Members(); + Members members; + members.reserve(value_.map_->size()); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + ObjectValues::const_iterator it = value_.map_->begin(); + ObjectValues::const_iterator itEnd = value_.map_->end(); + for (; it != itEnd; ++it) + members.push_back(std::string((*it).first.c_str())); +#else + ValueInternalMap::IteratorState it; + ValueInternalMap::IteratorState itEnd; + value_.map_->makeBeginIterator(it); + value_.map_->makeEndIterator(itEnd); + for (; !ValueInternalMap::equals(it, itEnd); ValueInternalMap::increment(it)) + members.push_back(std::string(ValueInternalMap::key(it))); +#endif + return members; +} +// +//# ifdef JSON_USE_CPPTL +// EnumMemberNames +// Value::enumMemberNames() const +//{ +// if ( type_ == objectValue ) +// { +// return CppTL::Enum::any( CppTL::Enum::transform( +// CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), +// MemberNamesTransform() ) ); +// } +// return EnumMemberNames(); +//} +// +// +// EnumValues +// Value::enumValues() const +//{ +// if ( type_ == objectValue || type_ == arrayValue ) +// return CppTL::Enum::anyValues( *(value_.map_), +// CppTL::Type() ); +// return EnumValues(); +//} +// +//# endif + +static bool IsIntegral(double d) { + double integral_part; + return modf(d, &integral_part) == 0.0; +} + +bool Value::isNull() const { return type_ == nullValue; } + +bool Value::isBool() const { return type_ == booleanValue; } + +bool Value::isInt() const { + switch (type_) { + case intValue: + return value_.int_ >= minInt && value_.int_ <= maxInt; + case uintValue: + return value_.uint_ <= UInt(maxInt); + case realValue: + return value_.real_ >= minInt && value_.real_ <= maxInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isUInt() const { + switch (type_) { + case intValue: + return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); + case uintValue: + return value_.uint_ <= maxUInt; + case realValue: + return value_.real_ >= 0 && value_.real_ <= maxUInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isInt64() const { +#if defined(JSON_HAS_INT64) + switch (type_) { + case intValue: + return true; + case uintValue: + return value_.uint_ <= UInt64(maxInt64); + case realValue: + // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a + // double, so double(maxInt64) will be rounded up to 2^63. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= double(minInt64) && + value_.real_ < double(maxInt64) && IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isUInt64() const { +#if defined(JSON_HAS_INT64) + switch (type_) { + case intValue: + return value_.int_ >= 0; + case uintValue: + return true; + case realValue: + // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a + // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && + IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isIntegral() const { +#if defined(JSON_HAS_INT64) + return isInt64() || isUInt64(); +#else + return isInt() || isUInt(); +#endif +} + +bool Value::isDouble() const { return type_ == realValue || isIntegral(); } + +bool Value::isNumeric() const { return isIntegral() || isDouble(); } + +bool Value::isString() const { return type_ == stringValue; } + +bool Value::isArray() const { return type_ == arrayValue; } + +bool Value::isObject() const { return type_ == objectValue; } + +void Value::setComment(const char* comment, CommentPlacement placement) { + if (!comments_) + comments_ = new CommentInfo[numberOfCommentPlacement]; + comments_[placement].setComment(comment); +} + +void Value::setComment(const std::string& comment, CommentPlacement placement) { + setComment(comment.c_str(), placement); +} + +bool Value::hasComment(CommentPlacement placement) const { + return comments_ != 0 && comments_[placement].comment_ != 0; +} + +std::string Value::getComment(CommentPlacement placement) const { + if (hasComment(placement)) + return comments_[placement].comment_; + return ""; +} + +void Value::setOffsetStart(size_t start) { start_ = start; } + +void Value::setOffsetLimit(size_t limit) { limit_ = limit; } + +size_t Value::getOffsetStart() const { return start_; } + +size_t Value::getOffsetLimit() const { return limit_; } + +std::string Value::toStyledString() const { + StyledWriter writer; + return writer.write(*this); +} + +Value::const_iterator Value::begin() const { + switch (type_) { +#ifdef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + if (value_.array_) { + ValueInternalArray::IteratorState it; + value_.array_->makeBeginIterator(it); + return const_iterator(it); + } + break; + case objectValue: + if (value_.map_) { + ValueInternalMap::IteratorState it; + value_.map_->makeBeginIterator(it); + return const_iterator(it); + } + break; +#else + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->begin()); + break; +#endif + default: + break; + } + return const_iterator(); +} + +Value::const_iterator Value::end() const { + switch (type_) { +#ifdef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + if (value_.array_) { + ValueInternalArray::IteratorState it; + value_.array_->makeEndIterator(it); + return const_iterator(it); + } + break; + case objectValue: + if (value_.map_) { + ValueInternalMap::IteratorState it; + value_.map_->makeEndIterator(it); + return const_iterator(it); + } + break; +#else + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->end()); + break; +#endif + default: + break; + } + return const_iterator(); +} + +Value::iterator Value::begin() { + switch (type_) { +#ifdef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + if (value_.array_) { + ValueInternalArray::IteratorState it; + value_.array_->makeBeginIterator(it); + return iterator(it); + } + break; + case objectValue: + if (value_.map_) { + ValueInternalMap::IteratorState it; + value_.map_->makeBeginIterator(it); + return iterator(it); + } + break; +#else + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->begin()); + break; +#endif + default: + break; + } + return iterator(); +} + +Value::iterator Value::end() { + switch (type_) { +#ifdef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + if (value_.array_) { + ValueInternalArray::IteratorState it; + value_.array_->makeEndIterator(it); + return iterator(it); + } + break; + case objectValue: + if (value_.map_) { + ValueInternalMap::IteratorState it; + value_.map_->makeEndIterator(it); + return iterator(it); + } + break; +#else + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->end()); + break; +#endif + default: + break; + } + return iterator(); +} + +// class PathArgument +// ////////////////////////////////////////////////////////////////// + +PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} + +PathArgument::PathArgument(ArrayIndex index) + : key_(), index_(index), kind_(kindIndex) {} + +PathArgument::PathArgument(const char* key) + : key_(key), index_(), kind_(kindKey) {} + +PathArgument::PathArgument(const std::string& key) + : key_(key.c_str()), index_(), kind_(kindKey) {} + +// class Path +// ////////////////////////////////////////////////////////////////// + +Path::Path(const std::string& path, + const PathArgument& a1, + const PathArgument& a2, + const PathArgument& a3, + const PathArgument& a4, + const PathArgument& a5) { + InArgs in; + in.push_back(&a1); + in.push_back(&a2); + in.push_back(&a3); + in.push_back(&a4); + in.push_back(&a5); + makePath(path, in); +} + +void Path::makePath(const std::string& path, const InArgs& in) { + const char* current = path.c_str(); + const char* end = current + path.length(); + InArgs::const_iterator itInArg = in.begin(); + while (current != end) { + if (*current == '[') { + ++current; + if (*current == '%') + addPathInArg(path, in, itInArg, PathArgument::kindIndex); + else { + ArrayIndex index = 0; + for (; current != end && *current >= '0' && *current <= '9'; ++current) + index = index * 10 + ArrayIndex(*current - '0'); + args_.push_back(index); + } + if (current == end || *current++ != ']') + invalidPath(path, int(current - path.c_str())); + } else if (*current == '%') { + addPathInArg(path, in, itInArg, PathArgument::kindKey); + ++current; + } else if (*current == '.') { + ++current; + } else { + const char* beginName = current; + while (current != end && !strchr("[.", *current)) + ++current; + args_.push_back(std::string(beginName, current)); + } + } +} + +void Path::addPathInArg(const std::string& /*path*/, + const InArgs& in, + InArgs::const_iterator& itInArg, + PathArgument::Kind kind) { + if (itInArg == in.end()) { + // Error: missing argument %d + } else if ((*itInArg)->kind_ != kind) { + // Error: bad argument type + } else { + args_.push_back(**itInArg); + } +} + +void Path::invalidPath(const std::string& /*path*/, int /*location*/) { + // Error: invalid path. +} + +const Value& Path::resolve(const Value& root) const { + const Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) { + // Error: unable to resolve path (array value expected at position... + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: unable to resolve path (object value expected at position...) + } + node = &((*node)[arg.key_]); + if (node == &Value::null) { + // Error: unable to resolve path (object has no member named '' at + // position...) + } + } + } + return *node; +} + +Value Path::resolve(const Value& root, const Value& defaultValue) const { + const Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) + return defaultValue; + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) + return defaultValue; + node = &((*node)[arg.key_]); + if (node == &Value::null) + return defaultValue; + } + } + return *node; +} + +Value& Path::make(Value& root) const { + Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray()) { + // Error: node is not an array at position ... + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: node is not an object at position... + } + node = &((*node)[arg.key_]); + } + } + return *node; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_value.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_writer.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2011 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include "json_tool.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below +#include +#define isfinite _finite +#define snprintf _snprintf +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +namespace Json { + +static bool containsControlCharacter(const char* str) { + while (*str) { + if (isControlCharacter(*(str++))) + return true; + } + return false; +} + +std::string valueToString(LargestInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + bool isNegative = value < 0; + if (isNegative) + value = -value; + uintToString(LargestUInt(value), current); + if (isNegative) + *--current = '-'; + assert(current >= buffer); + return current; +} + +std::string valueToString(LargestUInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + uintToString(value, current); + assert(current >= buffer); + return current; +} + +#if defined(JSON_HAS_INT64) + +std::string valueToString(Int value) { + return valueToString(LargestInt(value)); +} + +std::string valueToString(UInt value) { + return valueToString(LargestUInt(value)); +} + +#endif // # if defined(JSON_HAS_INT64) + +std::string valueToString(double value) { + // Allocate a buffer that is more than large enough to store the 16 digits of + // precision requested below. + char buffer[32]; + int len = -1; + +// Print into the buffer. We need not request the alternative representation +// that always has a decimal point because JSON doesn't distingish the +// concepts of reals and integers. +#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with + // visual studio 2005 to + // avoid warning. +#if defined(WINCE) + len = _snprintf(buffer, sizeof(buffer), "%.16g", value); +#else + len = sprintf_s(buffer, sizeof(buffer), "%.16g", value); +#endif +#else + if (isfinite(value)) { + len = snprintf(buffer, sizeof(buffer), "%.16g", value); + } else { + // IEEE standard states that NaN values will not compare to themselves + if (value != value) { + len = snprintf(buffer, sizeof(buffer), "null"); + } else if (value < 0) { + len = snprintf(buffer, sizeof(buffer), "-1e+9999"); + } else { + len = snprintf(buffer, sizeof(buffer), "1e+9999"); + } + // For those, we do not need to call fixNumLoc, but it is fast. + } +#endif + assert(len >= 0); + fixNumericLocale(buffer, buffer + len); + return buffer; +} + +std::string valueToString(bool value) { return value ? "true" : "false"; } + +std::string valueToQuotedString(const char* value) { + if (value == NULL) + return ""; + // Not sure how to handle unicode... + if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && + !containsControlCharacter(value)) + return std::string("\"") + value + "\""; + // We have to walk value and escape any special characters. + // Appending to std::string is not efficient, but this should be rare. + // (Note: forward slashes are *not* rare, but I am not escaping them.) + std::string::size_type maxsize = + strlen(value) * 2 + 3; // allescaped+quotes+NULL + std::string result; + result.reserve(maxsize); // to avoid lots of mallocs + result += "\""; + for (const char* c = value; *c != 0; ++c) { + switch (*c) { + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + // case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something. + // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); + result += oss.str(); + } else { + result += *c; + } + break; + } + } + result += "\""; + return result; +} + +// Class Writer +// ////////////////////////////////////////////////////////////////// +Writer::~Writer() {} + +// Class FastWriter +// ////////////////////////////////////////////////////////////////// + +FastWriter::FastWriter() + : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), + omitEndingLineFeed_(false) {} + +void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } + +void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } + +void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } + +std::string FastWriter::write(const Value& root) { + document_ = ""; + writeValue(root); + if (!omitEndingLineFeed_) + document_ += "\n"; + return document_; +} + +void FastWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + if (!dropNullPlaceholders_) + document_ += "null"; + break; + case intValue: + document_ += valueToString(value.asLargestInt()); + break; + case uintValue: + document_ += valueToString(value.asLargestUInt()); + break; + case realValue: + document_ += valueToString(value.asDouble()); + break; + case stringValue: + document_ += valueToQuotedString(value.asCString()); + break; + case booleanValue: + document_ += valueToString(value.asBool()); + break; + case arrayValue: { + document_ += "["; + int size = value.size(); + for (int index = 0; index < size; ++index) { + if (index > 0) + document_ += ","; + writeValue(value[index]); + } + document_ += "]"; + } break; + case objectValue: { + Value::Members members(value.getMemberNames()); + document_ += "{"; + for (Value::Members::iterator it = members.begin(); it != members.end(); + ++it) { + const std::string& name = *it; + if (it != members.begin()) + document_ += ","; + document_ += valueToQuotedString(name.c_str()); + document_ += yamlCompatiblityEnabled_ ? ": " : ":"; + writeValue(value[name]); + } + document_ += "}"; + } break; + } +} + +// Class StyledWriter +// ////////////////////////////////////////////////////////////////// + +StyledWriter::StyledWriter() + : rightMargin_(74), indentSize_(3), addChildValues_() {} + +std::string StyledWriter::write(const Value& root) { + document_ = ""; + addChildValues_ = false; + indentString_ = ""; + writeCommentBeforeValue(root); + writeValue(root); + writeCommentAfterValueOnSameLine(root); + document_ += "\n"; + return document_; +} + +void StyledWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: + pushValue(valueToQuotedString(value.asCString())); + break; + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const std::string& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + document_ += " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledWriter::writeArrayValue(const Value& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + writeIndent(); + writeValue(childValue); + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + document_ += "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + document_ += ", "; + document_ += childValues_[index]; + } + document_ += " ]"; + } + } +} + +bool StyledWriter::isMultineArray(const Value& value) { + int size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (int index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = + isMultiLine || ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (int index = 0; index < size; ++index) { + writeValue(value[index]); + lineLength += int(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledWriter::pushValue(const std::string& value) { + if (addChildValues_) + childValues_.push_back(value); + else + document_ += value; +} + +void StyledWriter::writeIndent() { + if (!document_.empty()) { + char last = document_[document_.length() - 1]; + if (last == ' ') // already indented + return; + if (last != '\n') // Comments may add new-line + document_ += '\n'; + } + document_ += indentString_; +} + +void StyledWriter::writeWithIndent(const std::string& value) { + writeIndent(); + document_ += value; +} + +void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); } + +void StyledWriter::unindent() { + assert(int(indentString_.size()) >= indentSize_); + indentString_.resize(indentString_.size() - indentSize_); +} + +void StyledWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + + document_ += "\n"; + writeIndent(); + std::string normalizedComment = normalizeEOL(root.getComment(commentBefore)); + std::string::const_iterator iter = normalizedComment.begin(); + while (iter != normalizedComment.end()) { + document_ += *iter; + if (*iter == '\n' && *(iter + 1) == '/') + writeIndent(); + ++iter; + } + + // Comments are stripped of newlines, so add one here + document_ += "\n"; +} + +void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + document_ += " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); + + if (root.hasComment(commentAfter)) { + document_ += "\n"; + document_ += normalizeEOL(root.getComment(commentAfter)); + document_ += "\n"; + } +} + +bool StyledWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +std::string StyledWriter::normalizeEOL(const std::string& text) { + std::string normalized; + normalized.reserve(text.length()); + const char* begin = text.c_str(); + const char* end = begin + text.length(); + const char* current = begin; + while (current != end) { + char c = *current++; + if (c == '\r') // mac or dos EOL + { + if (*current == '\n') // convert dos EOL + ++current; + normalized += '\n'; + } else // handle unix EOL & other char + normalized += c; + } + return normalized; +} + +// Class StyledStreamWriter +// ////////////////////////////////////////////////////////////////// + +StyledStreamWriter::StyledStreamWriter(std::string indentation) + : document_(NULL), rightMargin_(74), indentation_(indentation), + addChildValues_() {} + +void StyledStreamWriter::write(std::ostream& out, const Value& root) { + document_ = &out; + addChildValues_ = false; + indentString_ = ""; + writeCommentBeforeValue(root); + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *document_ << "\n"; + document_ = NULL; // Forget the stream, for safety. +} + +void StyledStreamWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: + pushValue(valueToQuotedString(value.asCString())); + break; + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const std::string& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + *document_ << " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledStreamWriter::writeArrayValue(const Value& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + writeIndent(); + writeValue(childValue); + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + *document_ << "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + *document_ << ", "; + *document_ << childValues_[index]; + } + *document_ << " ]"; + } + } +} + +bool StyledStreamWriter::isMultineArray(const Value& value) { + int size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (int index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = + isMultiLine || ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (int index = 0; index < size; ++index) { + writeValue(value[index]); + lineLength += int(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledStreamWriter::pushValue(const std::string& value) { + if (addChildValues_) + childValues_.push_back(value); + else + *document_ << value; +} + +void StyledStreamWriter::writeIndent() { + /* + Some comments in this method would have been nice. ;-) + + if ( !document_.empty() ) + { + char last = document_[document_.length()-1]; + if ( last == ' ' ) // already indented + return; + if ( last != '\n' ) // Comments may add new-line + *document_ << '\n'; + } + */ + *document_ << '\n' << indentString_; +} + +void StyledStreamWriter::writeWithIndent(const std::string& value) { + writeIndent(); + *document_ << value; +} + +void StyledStreamWriter::indent() { indentString_ += indentation_; } + +void StyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); +} + +void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + *document_ << normalizeEOL(root.getComment(commentBefore)); + *document_ << "\n"; +} + +void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + *document_ << " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); + + if (root.hasComment(commentAfter)) { + *document_ << "\n"; + *document_ << normalizeEOL(root.getComment(commentAfter)); + *document_ << "\n"; + } +} + +bool StyledStreamWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +std::string StyledStreamWriter::normalizeEOL(const std::string& text) { + std::string normalized; + normalized.reserve(text.length()); + const char* begin = text.c_str(); + const char* end = begin + text.length(); + const char* current = begin; + while (current != end) { + char c = *current++; + if (c == '\r') // mac or dos EOL + { + if (*current == '\n') // convert dos EOL + ++current; + normalized += '\n'; + } else // handle unix EOL & other char + normalized += c; + } + return normalized; +} + +std::ostream& operator<<(std::ostream& sout, const Value& root) { + Json::StyledStreamWriter writer; + writer.write(sout, root); + return sout; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_writer.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + diff --git a/single/jsoncpp/json-forwards.h b/cpp/jsoncpp/json-forwards.h similarity index 97% rename from single/jsoncpp/json-forwards.h rename to cpp/jsoncpp/json-forwards.h index fd21c05..18ace39 100644 --- a/single/jsoncpp/json-forwards.h +++ b/cpp/jsoncpp/json-forwards.h @@ -1,264 +1,264 @@ -/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/). -/// It is intented to be used with #include -/// This header provides forward declaration for all JsonCpp types. - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is -released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur - -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. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - -#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED -# define JSON_FORWARD_AMALGATED_H_INCLUDED -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -#define JSON_IS_AMALGAMATION - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_CONFIG_H_INCLUDED -#define JSON_CONFIG_H_INCLUDED - -/// If defined, indicates that json library is embedded in CppTL library. -//# define JSON_IN_CPPTL 1 - -/// If defined, indicates that json may leverage CppTL library -//# define JSON_USE_CPPTL 1 -/// If defined, indicates that cpptl vector based map should be used instead of -/// std::map -/// as Value container. -//# define JSON_USE_CPPTL_SMALLMAP 1 -/// If defined, indicates that Json specific container should be used -/// (hash table & simple deque container with customizable allocator). -/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 -//# define JSON_VALUE_USE_INTERNAL_MAP 1 -/// Force usage of standard new/malloc based allocator instead of memory pool -/// based allocator. -/// The memory pools allocator used optimization (initializing Value and -/// ValueInternalLink -/// as if it was a POD) that may cause some validation tool to report errors. -/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. -//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 - -// If non-zero, the library uses exceptions to report bad input instead of C -// assertion macros. The default is to use exceptions. -#ifndef JSON_USE_EXCEPTION -#define JSON_USE_EXCEPTION 1 -#endif - -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgated header. -// #define JSON_IS_AMALGAMATION - -#ifdef JSON_IN_CPPTL -#include -#ifndef JSON_USE_CPPTL -#define JSON_USE_CPPTL 1 -#endif -#endif - -#ifdef JSON_IN_CPPTL -#define JSON_API CPPTL_API -#elif defined(JSON_DLL_BUILD) -#if defined(_MSC_VER) -#define JSON_API __declspec(dllexport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#endif // if defined(_MSC_VER) -#elif defined(JSON_DLL) -#if defined(_MSC_VER) -#define JSON_API __declspec(dllimport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#endif // if defined(_MSC_VER) -#endif // ifdef JSON_IN_CPPTL -#if !defined(JSON_API) -#define JSON_API -#endif - -// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for -// integer -// Storages, and 64 bits integer support is disabled. -// #define JSON_NO_INT64 1 - -#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 -// Microsoft Visual Studio 6 only support conversion from __int64 to double -// (no conversion from unsigned __int64). -#define JSON_USE_INT64_DOUBLE_CONVERSION 1 -// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' -// characters in the debug information) -// All projects I've ever seen with VS6 were using this globally (not bothering -// with pragma push/pop). -#pragma warning(disable : 4786) -#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 - -#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 -/// Indicates that the following function is deprecated. -#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) -#endif - -#if !defined(JSONCPP_DEPRECATED) -#define JSONCPP_DEPRECATED(message) -#endif // if !defined(JSONCPP_DEPRECATED) - -namespace Json { -typedef int Int; -typedef unsigned int UInt; -#if defined(JSON_NO_INT64) -typedef int LargestInt; -typedef unsigned int LargestUInt; -#undef JSON_HAS_INT64 -#else // if defined(JSON_NO_INT64) -// For Microsoft Visual use specific types as long long is not supported -#if defined(_MSC_VER) // Microsoft Visual Studio -typedef __int64 Int64; -typedef unsigned __int64 UInt64; -#else // if defined(_MSC_VER) // Other platforms, use long long -typedef long long int Int64; -typedef unsigned long long int UInt64; -#endif // if defined(_MSC_VER) -typedef Int64 LargestInt; -typedef UInt64 LargestUInt; -#define JSON_HAS_INT64 -#endif // if defined(JSON_NO_INT64) -} // end namespace Json - -#endif // JSON_CONFIG_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_FORWARDS_H_INCLUDED -#define JSON_FORWARDS_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -// writer.h -class FastWriter; -class StyledWriter; - -// reader.h -class Reader; - -// features.h -class Features; - -// value.h -typedef unsigned int ArrayIndex; -class StaticString; -class Path; -class PathArgument; -class Value; -class ValueIteratorBase; -class ValueIterator; -class ValueConstIterator; -#ifdef JSON_VALUE_USE_INTERNAL_MAP -class ValueMapAllocator; -class ValueInternalLink; -class ValueInternalArray; -class ValueInternalMap; -#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - -} // namespace Json - -#endif // JSON_FORWARDS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - - - - - -#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED +/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/). +/// It is intented to be used with #include +/// This header provides forward declaration for all JsonCpp types. + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is +released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur + +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. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + +#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED +# define JSON_FORWARD_AMALGATED_H_INCLUDED +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +#define JSON_IS_AMALGAMATION + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +#define JSON_CONFIG_H_INCLUDED + +/// If defined, indicates that json library is embedded in CppTL library. +//# define JSON_IN_CPPTL 1 + +/// If defined, indicates that json may leverage CppTL library +//# define JSON_USE_CPPTL 1 +/// If defined, indicates that cpptl vector based map should be used instead of +/// std::map +/// as Value container. +//# define JSON_USE_CPPTL_SMALLMAP 1 +/// If defined, indicates that Json specific container should be used +/// (hash table & simple deque container with customizable allocator). +/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 +//# define JSON_VALUE_USE_INTERNAL_MAP 1 +/// Force usage of standard new/malloc based allocator instead of memory pool +/// based allocator. +/// The memory pools allocator used optimization (initializing Value and +/// ValueInternalLink +/// as if it was a POD) that may cause some validation tool to report errors. +/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. +//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 + +// If non-zero, the library uses exceptions to report bad input instead of C +// assertion macros. The default is to use exceptions. +#ifndef JSON_USE_EXCEPTION +#define JSON_USE_EXCEPTION 1 +#endif + +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgated header. +// #define JSON_IS_AMALGAMATION + +#ifdef JSON_IN_CPPTL +#include +#ifndef JSON_USE_CPPTL +#define JSON_USE_CPPTL 1 +#endif +#endif + +#ifdef JSON_IN_CPPTL +#define JSON_API CPPTL_API +#elif defined(JSON_DLL_BUILD) +#if defined(_MSC_VER) +#define JSON_API __declspec(dllexport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#elif defined(JSON_DLL) +#if defined(_MSC_VER) +#define JSON_API __declspec(dllimport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#endif // ifdef JSON_IN_CPPTL +#if !defined(JSON_API) +#define JSON_API +#endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 +// Microsoft Visual Studio 6 only support conversion from __int64 to double +// (no conversion from unsigned __int64). +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' +// characters in the debug information) +// All projects I've ever seen with VS6 were using this globally (not bothering +// with pragma push/pop). +#pragma warning(disable : 4786) +#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 + +#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 +/// Indicates that the following function is deprecated. +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#endif + +#if !defined(JSONCPP_DEPRECATED) +#define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +namespace Json { +typedef int Int; +typedef unsigned int UInt; +#if defined(JSON_NO_INT64) +typedef int LargestInt; +typedef unsigned int LargestUInt; +#undef JSON_HAS_INT64 +#else // if defined(JSON_NO_INT64) +// For Microsoft Visual use specific types as long long is not supported +#if defined(_MSC_VER) // Microsoft Visual Studio +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else // if defined(_MSC_VER) // Other platforms, use long long +typedef long long int Int64; +typedef unsigned long long int UInt64; +#endif // if defined(_MSC_VER) +typedef Int64 LargestInt; +typedef UInt64 LargestUInt; +#define JSON_HAS_INT64 +#endif // if defined(JSON_NO_INT64) +} // end namespace Json + +#endif // JSON_CONFIG_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +#define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// writer.h +class FastWriter; +class StyledWriter; + +// reader.h +class Reader; + +// features.h +class Features; + +// value.h +typedef unsigned int ArrayIndex; +class StaticString; +class Path; +class PathArgument; +class Value; +class ValueIteratorBase; +class ValueIterator; +class ValueConstIterator; +#ifdef JSON_VALUE_USE_INTERNAL_MAP +class ValueMapAllocator; +class ValueInternalLink; +class ValueInternalArray; +class ValueInternalMap; +#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP + +} // namespace Json + +#endif // JSON_FORWARDS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + + + + + +#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED diff --git a/jsoncpp/json.h b/cpp/jsoncpp/json.h similarity index 96% rename from jsoncpp/json.h rename to cpp/jsoncpp/json.h index 4dfc907..53da38c 100644 --- a/jsoncpp/json.h +++ b/cpp/jsoncpp/json.h @@ -1,2016 +1,2016 @@ -/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/). -/// It is intented to be used with #include - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is -released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur - -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. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - -#ifndef JSON_AMALGATED_H_INCLUDED -# define JSON_AMALGATED_H_INCLUDED -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -#define JSON_IS_AMALGAMATION - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/version.h -// ////////////////////////////////////////////////////////////////////// - -// DO NOT EDIT. This file is generated by CMake from "version" -// and "version.h.in" files. -// Run CMake configure step to update it. -#ifndef JSON_VERSION_H_INCLUDED -# define JSON_VERSION_H_INCLUDED - -# define JSONCPP_VERSION_STRING "0.7.0" -# define JSONCPP_VERSION_MAJOR 0 -# define JSONCPP_VERSION_MINOR 7 -# define JSONCPP_VERSION_PATCH 0 -# define JSONCPP_VERSION_QUALIFIER -# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) - -#endif // JSON_VERSION_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/version.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_CONFIG_H_INCLUDED -#define JSON_CONFIG_H_INCLUDED - -/// If defined, indicates that json library is embedded in CppTL library. -//# define JSON_IN_CPPTL 1 - -/// If defined, indicates that json may leverage CppTL library -//# define JSON_USE_CPPTL 1 -/// If defined, indicates that cpptl vector based map should be used instead of -/// std::map -/// as Value container. -//# define JSON_USE_CPPTL_SMALLMAP 1 -/// If defined, indicates that Json specific container should be used -/// (hash table & simple deque container with customizable allocator). -/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 -//# define JSON_VALUE_USE_INTERNAL_MAP 1 -/// Force usage of standard new/malloc based allocator instead of memory pool -/// based allocator. -/// The memory pools allocator used optimization (initializing Value and -/// ValueInternalLink -/// as if it was a POD) that may cause some validation tool to report errors. -/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. -//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 - -// If non-zero, the library uses exceptions to report bad input instead of C -// assertion macros. The default is to use exceptions. -#ifndef JSON_USE_EXCEPTION -#define JSON_USE_EXCEPTION 1 -#endif - -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgated header. -// #define JSON_IS_AMALGAMATION - -#ifdef JSON_IN_CPPTL -#include -#ifndef JSON_USE_CPPTL -#define JSON_USE_CPPTL 1 -#endif -#endif - -#ifdef JSON_IN_CPPTL -#define JSON_API CPPTL_API -#elif defined(JSON_DLL_BUILD) -#if defined(_MSC_VER) -#define JSON_API __declspec(dllexport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#endif // if defined(_MSC_VER) -#elif defined(JSON_DLL) -#if defined(_MSC_VER) -#define JSON_API __declspec(dllimport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#endif // if defined(_MSC_VER) -#endif // ifdef JSON_IN_CPPTL -#if !defined(JSON_API) -#define JSON_API -#endif - -// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for -// integer -// Storages, and 64 bits integer support is disabled. -// #define JSON_NO_INT64 1 - -#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 -// Microsoft Visual Studio 6 only support conversion from __int64 to double -// (no conversion from unsigned __int64). -#define JSON_USE_INT64_DOUBLE_CONVERSION 1 -// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' -// characters in the debug information) -// All projects I've ever seen with VS6 were using this globally (not bothering -// with pragma push/pop). -#pragma warning(disable : 4786) -#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 - -#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 -/// Indicates that the following function is deprecated. -#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) -#endif - -#if !defined(JSONCPP_DEPRECATED) -#define JSONCPP_DEPRECATED(message) -#endif // if !defined(JSONCPP_DEPRECATED) - -namespace Json { -typedef int Int; -typedef unsigned int UInt; -#if defined(JSON_NO_INT64) -typedef int LargestInt; -typedef unsigned int LargestUInt; -#undef JSON_HAS_INT64 -#else // if defined(JSON_NO_INT64) -// For Microsoft Visual use specific types as long long is not supported -#if defined(_MSC_VER) // Microsoft Visual Studio -typedef __int64 Int64; -typedef unsigned __int64 UInt64; -#else // if defined(_MSC_VER) // Other platforms, use long long -typedef long long int Int64; -typedef unsigned long long int UInt64; -#endif // if defined(_MSC_VER) -typedef Int64 LargestInt; -typedef UInt64 LargestUInt; -#define JSON_HAS_INT64 -#endif // if defined(JSON_NO_INT64) -} // end namespace Json - -#endif // JSON_CONFIG_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_FORWARDS_H_INCLUDED -#define JSON_FORWARDS_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -// writer.h -class FastWriter; -class StyledWriter; - -// reader.h -class Reader; - -// features.h -class Features; - -// value.h -typedef unsigned int ArrayIndex; -class StaticString; -class Path; -class PathArgument; -class Value; -class ValueIteratorBase; -class ValueIterator; -class ValueConstIterator; -#ifdef JSON_VALUE_USE_INTERNAL_MAP -class ValueMapAllocator; -class ValueInternalLink; -class ValueInternalArray; -class ValueInternalMap; -#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - -} // namespace Json - -#endif // JSON_FORWARDS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/features.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_FEATURES_H_INCLUDED -#define CPPTL_JSON_FEATURES_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -/** \brief Configuration passed to reader and writer. - * This configuration object can be used to force the Reader or Writer - * to behave in a standard conforming way. - */ -class JSON_API Features { -public: - /** \brief A configuration that allows all features and assumes all strings - * are UTF-8. - * - C & C++ comments are allowed - * - Root object can be any JSON value - * - Assumes Value strings are encoded in UTF-8 - */ - static Features all(); - - /** \brief A configuration that is strictly compatible with the JSON - * specification. - * - Comments are forbidden. - * - Root object must be either an array or an object value. - * - Assumes Value strings are encoded in UTF-8 - */ - static Features strictMode(); - - /** \brief Initialize the configuration like JsonConfig::allFeatures; - */ - Features(); - - /// \c true if comments are allowed. Default: \c true. - bool allowComments_; - - /// \c true if root must be either an array or an object value. Default: \c - /// false. - bool strictRoot_; - - /// \c true if dropped null placeholders are allowed. Default: \c false. - bool allowDroppedNullPlaceholders_; - - /// \c true if numeric object key are allowed. Default: \c false. - bool allowNumericKeys_; -}; - -} // namespace Json - -#endif // CPPTL_JSON_FEATURES_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/features.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/value.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_H_INCLUDED -#define CPPTL_JSON_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include - -#ifndef JSON_USE_CPPTL_SMALLMAP -#include -#else -#include -#endif -#ifdef JSON_USE_CPPTL -#include -#endif - -// Disable warning C4251: : needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -/** \brief JSON (JavaScript Object Notation). - */ -namespace Json { - -/** \brief Type of the value held by a Value object. - */ -enum ValueType { - nullValue = 0, ///< 'null' value - intValue, ///< signed integer value - uintValue, ///< unsigned integer value - realValue, ///< double value - stringValue, ///< UTF-8 string value - booleanValue, ///< bool value - arrayValue, ///< array value (ordered list) - objectValue ///< object value (collection of name/value pairs). -}; - -enum CommentPlacement { - commentBefore = 0, ///< a comment placed on the line before a value - commentAfterOnSameLine, ///< a comment just after a value on the same line - commentAfter, ///< a comment on the line after a value (only make sense for - /// root value) - numberOfCommentPlacement -}; - -//# ifdef JSON_USE_CPPTL -// typedef CppTL::AnyEnumerator EnumMemberNames; -// typedef CppTL::AnyEnumerator EnumValues; -//# endif - -/** \brief Lightweight wrapper to tag static string. - * - * Value constructor and objectValue member assignement takes advantage of the - * StaticString and avoid the cost of string duplication when storing the - * string or the member name. - * - * Example of usage: - * \code - * Json::Value aValue( StaticString("some text") ); - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ -class JSON_API StaticString { -public: - explicit StaticString(const char* czstring) : str_(czstring) {} - - operator const char*() const { return str_; } - - const char* c_str() const { return str_; } - -private: - const char* str_; -}; - -/** \brief Represents a JSON value. - * - * This class is a discriminated union wrapper that can represents a: - * - signed integer [range: Value::minInt - Value::maxInt] - * - unsigned integer (range: 0 - Value::maxUInt) - * - double - * - UTF-8 string - * - boolean - * - 'null' - * - an ordered list of Value - * - collection of name/value pairs (javascript object) - * - * The type of the held value is represented by a #ValueType and - * can be obtained using type(). - * - * values of an #objectValue or #arrayValue can be accessed using operator[]() - *methods. - * Non const methods will automatically create the a #nullValue element - * if it does not exist. - * The sequence of an #arrayValue will be automatically resize and initialized - * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. - * - * The get() methods can be used to obtanis default value in the case the - *required element - * does not exist. - * - * It is possible to iterate over the list of a #objectValue values using - * the getMemberNames() method. - */ -class JSON_API Value { - friend class ValueIteratorBase; -#ifdef JSON_VALUE_USE_INTERNAL_MAP - friend class ValueInternalLink; - friend class ValueInternalMap; -#endif -public: - typedef std::vector Members; - typedef ValueIterator iterator; - typedef ValueConstIterator const_iterator; - typedef Json::UInt UInt; - typedef Json::Int Int; -#if defined(JSON_HAS_INT64) - typedef Json::UInt64 UInt64; - typedef Json::Int64 Int64; -#endif // defined(JSON_HAS_INT64) - typedef Json::LargestInt LargestInt; - typedef Json::LargestUInt LargestUInt; - typedef Json::ArrayIndex ArrayIndex; - - static const Value& null; - /// Minimum signed integer value that can be stored in a Json::Value. - static const LargestInt minLargestInt; - /// Maximum signed integer value that can be stored in a Json::Value. - static const LargestInt maxLargestInt; - /// Maximum unsigned integer value that can be stored in a Json::Value. - static const LargestUInt maxLargestUInt; - - /// Minimum signed int value that can be stored in a Json::Value. - static const Int minInt; - /// Maximum signed int value that can be stored in a Json::Value. - static const Int maxInt; - /// Maximum unsigned int value that can be stored in a Json::Value. - static const UInt maxUInt; - -#if defined(JSON_HAS_INT64) - /// Minimum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 minInt64; - /// Maximum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 maxInt64; - /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. - static const UInt64 maxUInt64; -#endif // defined(JSON_HAS_INT64) - -private: -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION -#ifndef JSON_VALUE_USE_INTERNAL_MAP - class CZString { - public: - enum DuplicationPolicy { - noDuplication = 0, - duplicate, - duplicateOnCopy - }; - CZString(ArrayIndex index); - CZString(const char* cstr, DuplicationPolicy allocate); - CZString(const CZString& other); - ~CZString(); - CZString& operator=(CZString other); - bool operator<(const CZString& other) const; - bool operator==(const CZString& other) const; - ArrayIndex index() const; - const char* c_str() const; - bool isStaticString() const; - - private: - void swap(CZString& other); - const char* cstr_; - ArrayIndex index_; - }; - -public: -#ifndef JSON_USE_CPPTL_SMALLMAP - typedef std::map ObjectValues; -#else - typedef CppTL::SmallMap ObjectValues; -#endif // ifndef JSON_USE_CPPTL_SMALLMAP -#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP -#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - -public: - /** \brief Create a default Value of the given type. - - This is a very useful constructor. - To create an empty array, pass arrayValue. - To create an empty object, pass objectValue. - Another Value can then be set to this one by assignment. -This is useful since clear() and resize() will not alter types. - - Examples: -\code -Json::Value null_value; // null -Json::Value arr_value(Json::arrayValue); // [] -Json::Value obj_value(Json::objectValue); // {} -\endcode - */ - Value(ValueType type = nullValue); - Value(Int value); - Value(UInt value); -#if defined(JSON_HAS_INT64) - Value(Int64 value); - Value(UInt64 value); -#endif // if defined(JSON_HAS_INT64) - Value(double value); - Value(const char* value); - Value(const char* beginValue, const char* endValue); - /** \brief Constructs a value from a static string. - - * Like other value string constructor but do not duplicate the string for - * internal storage. The given string must remain alive after the call to this - * constructor. - * Example of usage: - * \code - * Json::Value aValue( StaticString("some text") ); - * \endcode - */ - Value(const StaticString& value); - Value(const std::string& value); -#ifdef JSON_USE_CPPTL - Value(const CppTL::ConstString& value); -#endif - Value(bool value); - Value(const Value& other); - ~Value(); - - Value& operator=(Value other); - /// Swap values. - /// \note Currently, comments are intentionally not swapped, for - /// both logic and efficiency. - void swap(Value& other); - - ValueType type() const; - - bool operator<(const Value& other) const; - bool operator<=(const Value& other) const; - bool operator>=(const Value& other) const; - bool operator>(const Value& other) const; - - bool operator==(const Value& other) const; - bool operator!=(const Value& other) const; - - int compare(const Value& other) const; - - const char* asCString() const; - std::string asString() const; -#ifdef JSON_USE_CPPTL - CppTL::ConstString asConstString() const; -#endif - Int asInt() const; - UInt asUInt() const; -#if defined(JSON_HAS_INT64) - Int64 asInt64() const; - UInt64 asUInt64() const; -#endif // if defined(JSON_HAS_INT64) - LargestInt asLargestInt() const; - LargestUInt asLargestUInt() const; - float asFloat() const; - double asDouble() const; - bool asBool() const; - - bool isNull() const; - bool isBool() const; - bool isInt() const; - bool isInt64() const; - bool isUInt() const; - bool isUInt64() const; - bool isIntegral() const; - bool isDouble() const; - bool isNumeric() const; - bool isString() const; - bool isArray() const; - bool isObject() const; - - bool isConvertibleTo(ValueType other) const; - - /// Number of values in array or object - ArrayIndex size() const; - - /// \brief Return true if empty array, empty object, or null; - /// otherwise, false. - bool empty() const; - - /// Return isNull() - bool operator!() const; - - /// Remove all object members and array elements. - /// \pre type() is arrayValue, objectValue, or nullValue - /// \post type() is unchanged - void clear(); - - /// Resize the array to size elements. - /// New elements are initialized to null. - /// May only be called on nullValue or arrayValue. - /// \pre type() is arrayValue or nullValue - /// \post type() is arrayValue - void resize(ArrayIndex size); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are - /// inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value& operator[](ArrayIndex index); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are - /// inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value& operator[](int index); - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value& operator[](ArrayIndex index) const; - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value& operator[](int index) const; - - /// If the array contains at least index+1 elements, returns the element - /// value, - /// otherwise returns defaultValue. - Value get(ArrayIndex index, const Value& defaultValue) const; - /// Return true if index < size(). - bool isValidIndex(ArrayIndex index) const; - /// \brief Append value to array at the end. - /// - /// Equivalent to jsonvalue[jsonvalue.size()] = value; - Value& append(const Value& value); - - /// Access an object value by name, create a null member if it does not exist. - Value& operator[](const char* key); - /// Access an object value by name, returns null if there is no member with - /// that name. - const Value& operator[](const char* key) const; - /// Access an object value by name, create a null member if it does not exist. - Value& operator[](const std::string& key); - /// Access an object value by name, returns null if there is no member with - /// that name. - const Value& operator[](const std::string& key) const; - /** \brief Access an object value by name, create a null member if it does not - exist. - - * If the object as no entry for that name, then the member name used to store - * the new entry is not duplicated. - * Example of use: - * \code - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ - Value& operator[](const StaticString& key); -#ifdef JSON_USE_CPPTL - /// Access an object value by name, create a null member if it does not exist. - Value& operator[](const CppTL::ConstString& key); - /// Access an object value by name, returns null if there is no member with - /// that name. - const Value& operator[](const CppTL::ConstString& key) const; -#endif - /// Return the member named key if it exist, defaultValue otherwise. - Value get(const char* key, const Value& defaultValue) const; - /// Return the member named key if it exist, defaultValue otherwise. - Value get(const std::string& key, const Value& defaultValue) const; -#ifdef JSON_USE_CPPTL - /// Return the member named key if it exist, defaultValue otherwise. - Value get(const CppTL::ConstString& key, const Value& defaultValue) const; -#endif - /// \brief Remove and return the named member. - /// - /// Do nothing if it did not exist. - /// \return the removed Value, or null. - /// \pre type() is objectValue or nullValue - /// \post type() is unchanged - Value removeMember(const char* key); - /// Same as removeMember(const char*) - Value removeMember(const std::string& key); - - /// Return true if the object has a member named key. - bool isMember(const char* key) const; - /// Return true if the object has a member named key. - bool isMember(const std::string& key) const; -#ifdef JSON_USE_CPPTL - /// Return true if the object has a member named key. - bool isMember(const CppTL::ConstString& key) const; -#endif - - /// \brief Return a list of the member names. - /// - /// If null, return an empty list. - /// \pre type() is objectValue or nullValue - /// \post if type() was nullValue, it remains nullValue - Members getMemberNames() const; - - //# ifdef JSON_USE_CPPTL - // EnumMemberNames enumMemberNames() const; - // EnumValues enumValues() const; - //# endif - - /// Comments must be //... or /* ... */ - void setComment(const char* comment, CommentPlacement placement); - /// Comments must be //... or /* ... */ - void setComment(const std::string& comment, CommentPlacement placement); - bool hasComment(CommentPlacement placement) const; - /// Include delimiters and embedded newlines. - std::string getComment(CommentPlacement placement) const; - - std::string toStyledString() const; - - const_iterator begin() const; - const_iterator end() const; - - iterator begin(); - iterator end(); - - // Accessors for the [start, limit) range of bytes within the JSON text from - // which this value was parsed, if any. - void setOffsetStart(size_t start); - void setOffsetLimit(size_t limit); - size_t getOffsetStart() const; - size_t getOffsetLimit() const; - -private: - Value& resolveReference(const char* key, bool isStatic); - -#ifdef JSON_VALUE_USE_INTERNAL_MAP - inline bool isItemAvailable() const { return itemIsUsed_ == 0; } - - inline void setItemUsed(bool isUsed = true) { itemIsUsed_ = isUsed ? 1 : 0; } - - inline bool isMemberNameStatic() const { return memberNameIsStatic_ == 0; } - - inline void setMemberNameIsStatic(bool isStatic) { - memberNameIsStatic_ = isStatic ? 1 : 0; - } -#endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP - -private: - struct CommentInfo { - CommentInfo(); - ~CommentInfo(); - - void setComment(const char* text); - - char* comment_; - }; - - // struct MemberNamesTransform - //{ - // typedef const char *result_type; - // const char *operator()( const CZString &name ) const - // { - // return name.c_str(); - // } - //}; - - union ValueHolder { - LargestInt int_; - LargestUInt uint_; - double real_; - bool bool_; - char* string_; -#ifdef JSON_VALUE_USE_INTERNAL_MAP - ValueInternalArray* array_; - ValueInternalMap* map_; -#else - ObjectValues* map_; -#endif - } value_; - ValueType type_ : 8; - int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. -#ifdef JSON_VALUE_USE_INTERNAL_MAP - unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. - int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. -#endif - CommentInfo* comments_; - - // [start, limit) byte offsets in the source JSON text from which this Value - // was extracted. - size_t start_; - size_t limit_; -}; - -/** \brief Experimental and untested: represents an element of the "path" to - * access a node. - */ -class JSON_API PathArgument { -public: - friend class Path; - - PathArgument(); - PathArgument(ArrayIndex index); - PathArgument(const char* key); - PathArgument(const std::string& key); - -private: - enum Kind { - kindNone = 0, - kindIndex, - kindKey - }; - std::string key_; - ArrayIndex index_; - Kind kind_; -}; - -/** \brief Experimental and untested: represents a "path" to access a node. - * - * Syntax: - * - "." => root node - * - ".[n]" => elements at index 'n' of root node (an array value) - * - ".name" => member named 'name' of root node (an object value) - * - ".name1.name2.name3" - * - ".[0][1][2].name1[3]" - * - ".%" => member name is provided as parameter - * - ".[%]" => index is provied as parameter - */ -class JSON_API Path { -public: - Path(const std::string& path, - const PathArgument& a1 = PathArgument(), - const PathArgument& a2 = PathArgument(), - const PathArgument& a3 = PathArgument(), - const PathArgument& a4 = PathArgument(), - const PathArgument& a5 = PathArgument()); - - const Value& resolve(const Value& root) const; - Value resolve(const Value& root, const Value& defaultValue) const; - /// Creates the "path" to access the specified node and returns a reference on - /// the node. - Value& make(Value& root) const; - -private: - typedef std::vector InArgs; - typedef std::vector Args; - - void makePath(const std::string& path, const InArgs& in); - void addPathInArg(const std::string& path, - const InArgs& in, - InArgs::const_iterator& itInArg, - PathArgument::Kind kind); - void invalidPath(const std::string& path, int location); - - Args args_; -}; - -#ifdef JSON_VALUE_USE_INTERNAL_MAP -/** \brief Allocator to customize Value internal map. - * Below is an example of a simple implementation (default implementation - actually - * use memory pool for speed). - * \code - class DefaultValueMapAllocator : public ValueMapAllocator - { - public: // overridden from ValueMapAllocator - virtual ValueInternalMap *newMap() - { - return new ValueInternalMap(); - } - - virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) - { - return new ValueInternalMap( other ); - } - - virtual void destructMap( ValueInternalMap *map ) - { - delete map; - } - - virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) - { - return new ValueInternalLink[size]; - } - - virtual void releaseMapBuckets( ValueInternalLink *links ) - { - delete [] links; - } - - virtual ValueInternalLink *allocateMapLink() - { - return new ValueInternalLink(); - } - - virtual void releaseMapLink( ValueInternalLink *link ) - { - delete link; - } - }; - * \endcode - */ -class JSON_API ValueMapAllocator { -public: - virtual ~ValueMapAllocator(); - virtual ValueInternalMap* newMap() = 0; - virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) = 0; - virtual void destructMap(ValueInternalMap* map) = 0; - virtual ValueInternalLink* allocateMapBuckets(unsigned int size) = 0; - virtual void releaseMapBuckets(ValueInternalLink* links) = 0; - virtual ValueInternalLink* allocateMapLink() = 0; - virtual void releaseMapLink(ValueInternalLink* link) = 0; -}; - -/** \brief ValueInternalMap hash-map bucket chain link (for internal use only). - * \internal previous_ & next_ allows for bidirectional traversal. - */ -class JSON_API ValueInternalLink { -public: - enum { - itemPerLink = 6 - }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. - enum InternalFlags { - flagAvailable = 0, - flagUsed = 1 - }; - - ValueInternalLink(); - - ~ValueInternalLink(); - - Value items_[itemPerLink]; - char* keys_[itemPerLink]; - ValueInternalLink* previous_; - ValueInternalLink* next_; -}; - -/** \brief A linked page based hash-table implementation used internally by - *Value. - * \internal ValueInternalMap is a tradional bucket based hash-table, with a - *linked - * list in each bucket to handle collision. There is an addional twist in that - * each node of the collision linked list is a page containing a fixed amount of - * value. This provides a better compromise between memory usage and speed. - * - * Each bucket is made up of a chained list of ValueInternalLink. The last - * link of a given bucket can be found in the 'previous_' field of the following - *bucket. - * The last link of the last bucket is stored in tailLink_ as it has no - *following bucket. - * Only the last link of a bucket may contains 'available' item. The last link - *always - * contains at least one element unless is it the bucket one very first link. - */ -class JSON_API ValueInternalMap { - friend class ValueIteratorBase; - friend class Value; - -public: - typedef unsigned int HashKey; - typedef unsigned int BucketIndex; - -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - struct IteratorState { - IteratorState() : map_(0), link_(0), itemIndex_(0), bucketIndex_(0) {} - ValueInternalMap* map_; - ValueInternalLink* link_; - BucketIndex itemIndex_; - BucketIndex bucketIndex_; - }; -#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - - ValueInternalMap(); - ValueInternalMap(const ValueInternalMap& other); - ValueInternalMap& operator=(ValueInternalMap other); - ~ValueInternalMap(); - - void swap(ValueInternalMap& other); - - BucketIndex size() const; - - void clear(); - - bool reserveDelta(BucketIndex growth); - - bool reserve(BucketIndex newItemCount); - - const Value* find(const char* key) const; - - Value* find(const char* key); - - Value& resolveReference(const char* key, bool isStatic); - - void remove(const char* key); - - void doActualRemove(ValueInternalLink* link, - BucketIndex index, - BucketIndex bucketIndex); - - ValueInternalLink*& getLastLinkInBucket(BucketIndex bucketIndex); - - Value& setNewItem(const char* key, - bool isStatic, - ValueInternalLink* link, - BucketIndex index); - - Value& unsafeAdd(const char* key, bool isStatic, HashKey hashedKey); - - HashKey hash(const char* key) const; - - int compare(const ValueInternalMap& other) const; - -private: - void makeBeginIterator(IteratorState& it) const; - void makeEndIterator(IteratorState& it) const; - static bool equals(const IteratorState& x, const IteratorState& other); - static void increment(IteratorState& iterator); - static void incrementBucket(IteratorState& iterator); - static void decrement(IteratorState& iterator); - static const char* key(const IteratorState& iterator); - static const char* key(const IteratorState& iterator, bool& isStatic); - static Value& value(const IteratorState& iterator); - static int distance(const IteratorState& x, const IteratorState& y); - -private: - ValueInternalLink* buckets_; - ValueInternalLink* tailLink_; - BucketIndex bucketsSize_; - BucketIndex itemCount_; -}; - -/** \brief A simplified deque implementation used internally by Value. -* \internal -* It is based on a list of fixed "page", each page contains a fixed number of -*items. -* Instead of using a linked-list, a array of pointer is used for fast item -*look-up. -* Look-up for an element is as follow: -* - compute page index: pageIndex = itemIndex / itemsPerPage -* - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] -* -* Insertion is amortized constant time (only the array containing the index of -*pointers -* need to be reallocated when items are appended). -*/ -class JSON_API ValueInternalArray { - friend class Value; - friend class ValueIteratorBase; - -public: - enum { - itemsPerPage = 8 - }; // should be a power of 2 for fast divide and modulo. - typedef Value::ArrayIndex ArrayIndex; - typedef unsigned int PageIndex; - -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - struct IteratorState // Must be a POD - { - IteratorState() : array_(0), currentPageIndex_(0), currentItemIndex_(0) {} - ValueInternalArray* array_; - Value** currentPageIndex_; - unsigned int currentItemIndex_; - }; -#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - - ValueInternalArray(); - ValueInternalArray(const ValueInternalArray& other); - ValueInternalArray& operator=(ValueInternalArray other); - ~ValueInternalArray(); - void swap(ValueInternalArray& other); - - void clear(); - void resize(ArrayIndex newSize); - - Value& resolveReference(ArrayIndex index); - - Value* find(ArrayIndex index) const; - - ArrayIndex size() const; - - int compare(const ValueInternalArray& other) const; - -private: - static bool equals(const IteratorState& x, const IteratorState& other); - static void increment(IteratorState& iterator); - static void decrement(IteratorState& iterator); - static Value& dereference(const IteratorState& iterator); - static Value& unsafeDereference(const IteratorState& iterator); - static int distance(const IteratorState& x, const IteratorState& y); - static ArrayIndex indexOf(const IteratorState& iterator); - void makeBeginIterator(IteratorState& it) const; - void makeEndIterator(IteratorState& it) const; - void makeIterator(IteratorState& it, ArrayIndex index) const; - - void makeIndexValid(ArrayIndex index); - - Value** pages_; - ArrayIndex size_; - PageIndex pageCount_; -}; - -/** \brief Experimental: do not use. Allocator to customize Value internal -array. - * Below is an example of a simple implementation (actual implementation use - * memory pool). - \code -class DefaultValueArrayAllocator : public ValueArrayAllocator -{ -public: // overridden from ValueArrayAllocator -virtual ~DefaultValueArrayAllocator() -{ -} - -virtual ValueInternalArray *newArray() -{ - return new ValueInternalArray(); -} - -virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) -{ - return new ValueInternalArray( other ); -} - -virtual void destruct( ValueInternalArray *array ) -{ - delete array; -} - -virtual void reallocateArrayPageIndex( Value **&indexes, - ValueInternalArray::PageIndex -&indexCount, - ValueInternalArray::PageIndex -minNewIndexCount ) -{ - ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; - if ( minNewIndexCount > newIndexCount ) - newIndexCount = minNewIndexCount; - void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); - if ( !newIndexes ) - throw std::bad_alloc(); - indexCount = newIndexCount; - indexes = static_cast( newIndexes ); -} -virtual void releaseArrayPageIndex( Value **indexes, - ValueInternalArray::PageIndex indexCount ) -{ - if ( indexes ) - free( indexes ); -} - -virtual Value *allocateArrayPage() -{ - return static_cast( malloc( sizeof(Value) * -ValueInternalArray::itemsPerPage ) ); -} - -virtual void releaseArrayPage( Value *value ) -{ - if ( value ) - free( value ); -} -}; - \endcode - */ -class JSON_API ValueArrayAllocator { -public: - virtual ~ValueArrayAllocator(); - virtual ValueInternalArray* newArray() = 0; - virtual ValueInternalArray* newArrayCopy(const ValueInternalArray& other) = 0; - virtual void destructArray(ValueInternalArray* array) = 0; - /** \brief Reallocate array page index. - * Reallocates an array of pointer on each page. - * \param indexes [input] pointer on the current index. May be \c NULL. - * [output] pointer on the new index of at least - * \a minNewIndexCount pages. - * \param indexCount [input] current number of pages in the index. - * [output] number of page the reallocated index can handle. - * \b MUST be >= \a minNewIndexCount. - * \param minNewIndexCount Minimum number of page the new index must be able - * to - * handle. - */ - virtual void - reallocateArrayPageIndex(Value**& indexes, - ValueInternalArray::PageIndex& indexCount, - ValueInternalArray::PageIndex minNewIndexCount) = 0; - virtual void - releaseArrayPageIndex(Value** indexes, - ValueInternalArray::PageIndex indexCount) = 0; - virtual Value* allocateArrayPage() = 0; - virtual void releaseArrayPage(Value* value) = 0; -}; -#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - -/** \brief base class for Value iterators. - * - */ -class JSON_API ValueIteratorBase { -public: - typedef std::bidirectional_iterator_tag iterator_category; - typedef unsigned int size_t; - typedef int difference_type; - typedef ValueIteratorBase SelfType; - - ValueIteratorBase(); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); -#else - ValueIteratorBase(const ValueInternalArray::IteratorState& state); - ValueIteratorBase(const ValueInternalMap::IteratorState& state); -#endif - - bool operator==(const SelfType& other) const { return isEqual(other); } - - bool operator!=(const SelfType& other) const { return !isEqual(other); } - - difference_type operator-(const SelfType& other) const { - return computeDistance(other); - } - - /// Return either the index or the member name of the referenced value as a - /// Value. - Value key() const; - - /// Return the index of the referenced Value. -1 if it is not an arrayValue. - UInt index() const; - - /// Return the member name of the referenced Value. "" if it is not an - /// objectValue. - const char* memberName() const; - -protected: - Value& deref() const; - - void increment(); - - void decrement(); - - difference_type computeDistance(const SelfType& other) const; - - bool isEqual(const SelfType& other) const; - - void copy(const SelfType& other); - -private: -#ifndef JSON_VALUE_USE_INTERNAL_MAP - Value::ObjectValues::iterator current_; - // Indicates that iterator is for a null value. - bool isNull_; -#else - union { - ValueInternalArray::IteratorState array_; - ValueInternalMap::IteratorState map_; - } iterator_; - bool isArray_; -#endif -}; - -/** \brief const iterator for object and array value. - * - */ -class JSON_API ValueConstIterator : public ValueIteratorBase { - friend class Value; - -public: - typedef const Value value_type; - typedef unsigned int size_t; - typedef int difference_type; - typedef const Value& reference; - typedef const Value* pointer; - typedef ValueConstIterator SelfType; - - ValueConstIterator(); - -private: -/*! \internal Use by Value to create an iterator. - */ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueConstIterator(const Value::ObjectValues::iterator& current); -#else - ValueConstIterator(const ValueInternalArray::IteratorState& state); - ValueConstIterator(const ValueInternalMap::IteratorState& state); -#endif -public: - SelfType& operator=(const ValueIteratorBase& other); - - SelfType operator++(int) { - SelfType temp(*this); - ++*this; - return temp; - } - - SelfType operator--(int) { - SelfType temp(*this); - --*this; - return temp; - } - - SelfType& operator--() { - decrement(); - return *this; - } - - SelfType& operator++() { - increment(); - return *this; - } - - reference operator*() const { return deref(); } - - pointer operator->() const { return &deref(); } -}; - -/** \brief Iterator for object and array value. - */ -class JSON_API ValueIterator : public ValueIteratorBase { - friend class Value; - -public: - typedef Value value_type; - typedef unsigned int size_t; - typedef int difference_type; - typedef Value& reference; - typedef Value* pointer; - typedef ValueIterator SelfType; - - ValueIterator(); - ValueIterator(const ValueConstIterator& other); - ValueIterator(const ValueIterator& other); - -private: -/*! \internal Use by Value to create an iterator. - */ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueIterator(const Value::ObjectValues::iterator& current); -#else - ValueIterator(const ValueInternalArray::IteratorState& state); - ValueIterator(const ValueInternalMap::IteratorState& state); -#endif -public: - SelfType& operator=(const SelfType& other); - - SelfType operator++(int) { - SelfType temp(*this); - ++*this; - return temp; - } - - SelfType operator--(int) { - SelfType temp(*this); - --*this; - return temp; - } - - SelfType& operator--() { - decrement(); - return *this; - } - - SelfType& operator++() { - increment(); - return *this; - } - - reference operator*() const { return deref(); } - - pointer operator->() const { return &deref(); } -}; - -} // namespace Json - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // CPPTL_JSON_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/value.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/reader.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_READER_H_INCLUDED -#define CPPTL_JSON_READER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "features.h" -#include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include - -// Disable warning C4251: : needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -namespace Json { - -/** \brief Unserialize a JSON document into a - *Value. - * - */ -class JSON_API Reader { -public: - typedef char Char; - typedef const Char* Location; - - /** \brief An error tagged with where in the JSON text it was encountered. - * - * The offsets give the [start, limit) range of bytes within the text. Note - * that this is bytes, not codepoints. - * - */ - struct StructuredError { - size_t offset_start; - size_t offset_limit; - std::string message; - }; - - /** \brief Constructs a Reader allowing all features - * for parsing. - */ - Reader(); - - /** \brief Constructs a Reader allowing the specified feature set - * for parsing. - */ - Reader(const Features& features); - - /** \brief Read a Value from a JSON - * document. - * \param document UTF-8 encoded string containing the document to read. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them - * back during - * serialization, \c false to discard comments. - * This parameter is ignored if - * Features::allowComments_ - * is \c false. - * \return \c true if the document was successfully parsed, \c false if an - * error occurred. - */ - bool - parse(const std::string& document, Value& root, bool collectComments = true); - - /** \brief Read a Value from a JSON - document. - * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the - document to read. - * \param endDoc Pointer on the end of the UTF-8 encoded string of the - document to read. - \ Must be >= beginDoc. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them - back during - * serialization, \c false to discard comments. - * This parameter is ignored if - Features::allowComments_ - * is \c false. - * \return \c true if the document was successfully parsed, \c false if an - error occurred. - */ - bool parse(const char* beginDoc, - const char* endDoc, - Value& root, - bool collectComments = true); - - /// \brief Parse from input stream. - /// \see Json::operator>>(std::istream&, Json::Value&). - bool parse(std::istream& is, Value& root, bool collectComments = true); - - /** \brief Returns a user friendly string that list errors in the parsed - * document. - * \return Formatted error message with the list of errors with their location - * in - * the parsed document. An empty string is returned if no error - * occurred - * during parsing. - * \deprecated Use getFormattedErrorMessages() instead (typo fix). - */ - JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") - std::string getFormatedErrorMessages() const; - - /** \brief Returns a user friendly string that list errors in the parsed - * document. - * \return Formatted error message with the list of errors with their location - * in - * the parsed document. An empty string is returned if no error - * occurred - * during parsing. - */ - std::string getFormattedErrorMessages() const; - - /** \brief Returns a vector of structured erros encounted while parsing. - * \return A (possibly empty) vector of StructuredError objects. Currently - * only one error can be returned, but the caller should tolerate - * multiple - * errors. This can occur if the parser recovers from a non-fatal - * parse error and then encounters additional errors. - */ - std::vector getStructuredErrors() const; - -private: - enum TokenType { - tokenEndOfStream = 0, - tokenObjectBegin, - tokenObjectEnd, - tokenArrayBegin, - tokenArrayEnd, - tokenString, - tokenNumber, - tokenTrue, - tokenFalse, - tokenNull, - tokenArraySeparator, - tokenMemberSeparator, - tokenComment, - tokenError - }; - - class Token { - public: - TokenType type_; - Location start_; - Location end_; - }; - - class ErrorInfo { - public: - Token token_; - std::string message_; - Location extra_; - }; - - typedef std::deque Errors; - - bool expectToken(TokenType type, Token& token, const char* message); - bool readToken(Token& token); - void skipSpaces(); - bool match(Location pattern, int patternLength); - bool readComment(); - bool readCStyleComment(); - bool readCppStyleComment(); - bool readString(); - void readNumber(); - bool readValue(); - bool readObject(Token& token); - bool readArray(Token& token); - bool decodeNumber(Token& token); - bool decodeNumber(Token& token, Value& decoded); - bool decodeString(Token& token); - bool decodeString(Token& token, std::string& decoded); - bool decodeDouble(Token& token); - bool decodeDouble(Token& token, Value& decoded); - bool decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode); - bool decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& unicode); - bool addError(const std::string& message, Token& token, Location extra = 0); - bool recoverFromError(TokenType skipUntilToken); - bool addErrorAndRecover(const std::string& message, - Token& token, - TokenType skipUntilToken); - void skipUntilSpace(); - Value& currentValue(); - Char getNextChar(); - void - getLocationLineAndColumn(Location location, int& line, int& column) const; - std::string getLocationLineAndColumn(Location location) const; - void addComment(Location begin, Location end, CommentPlacement placement); - void skipCommentTokens(Token& token); - - typedef std::stack Nodes; - Nodes nodes_; - Errors errors_; - std::string document_; - Location begin_; - Location end_; - Location current_; - Location lastValueEnd_; - Value* lastValue_; - std::string commentsBefore_; - Features features_; - bool collectComments_; -}; - -/** \brief Read from 'sin' into 'root'. - - Always keep comments from the input JSON. - - This can be used to read a file into a particular sub-object. - For example: - \code - Json::Value root; - cin >> root["dir"]["file"]; - cout << root; - \endcode - Result: - \verbatim - { - "dir": { - "file": { - // The input stream JSON would be nested here. - } - } - } - \endverbatim - \throw std::exception on parse error. - \see Json::operator<<() -*/ -JSON_API std::istream& operator>>(std::istream&, Value&); - -} // namespace Json - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // CPPTL_JSON_READER_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/reader.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/writer.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_WRITER_H_INCLUDED -#define JSON_WRITER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include - -// Disable warning C4251: : needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -namespace Json { - -class Value; - -/** \brief Abstract class for writers. - */ -class JSON_API Writer { -public: - virtual ~Writer(); - - virtual std::string write(const Value& root) = 0; -}; - -/** \brief Outputs a Value in JSON format - *without formatting (not human friendly). - * - * The JSON document is written in a single line. It is not intended for 'human' - *consumption, - * but may be usefull to support feature such as RPC where bandwith is limited. - * \sa Reader, Value - */ -class JSON_API FastWriter : public Writer { -public: - FastWriter(); - virtual ~FastWriter() {} - - void enableYAMLCompatibility(); - - /** \brief Drop the "null" string from the writer's output for nullValues. - * Strictly speaking, this is not valid JSON. But when the output is being - * fed to a browser's Javascript, it makes for smaller output and the - * browser can handle the output just fine. - */ - void dropNullPlaceholders(); - - void omitEndingLineFeed(); - -public: // overridden from Writer - virtual std::string write(const Value& root); - -private: - void writeValue(const Value& value); - - std::string document_; - bool yamlCompatiblityEnabled_; - bool dropNullPlaceholders_; - bool omitEndingLineFeed_; -}; - -/** \brief Writes a Value in JSON format in a - *human friendly way. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per - *line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value - *types, - * and all the values fit on one lines, then print the array on a single - *line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their - *#CommentPlacement. - * - * \sa Reader, Value, Value::setComment() - */ -class JSON_API StyledWriter : public Writer { -public: - StyledWriter(); - virtual ~StyledWriter() {} - -public: // overridden from Writer - /** \brief Serialize a Value in JSON format. - * \param root Value to serialize. - * \return String containing the JSON document that represents the root value. - */ - virtual std::string write(const Value& root); - -private: - void writeValue(const Value& value); - void writeArrayValue(const Value& value); - bool isMultineArray(const Value& value); - void pushValue(const std::string& value); - void writeIndent(); - void writeWithIndent(const std::string& value); - void indent(); - void unindent(); - void writeCommentBeforeValue(const Value& root); - void writeCommentAfterValueOnSameLine(const Value& root); - bool hasCommentForValue(const Value& value); - static std::string normalizeEOL(const std::string& text); - - typedef std::vector ChildValues; - - ChildValues childValues_; - std::string document_; - std::string indentString_; - int rightMargin_; - int indentSize_; - bool addChildValues_; -}; - -/** \brief Writes a Value in JSON format in a - human friendly way, - to a stream rather than to a string. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per - line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value - types, - * and all the values fit on one lines, then print the array on a single - line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their - #CommentPlacement. - * - * \param indentation Each level will be indented by this amount extra. - * \sa Reader, Value, Value::setComment() - */ -class JSON_API StyledStreamWriter { -public: - StyledStreamWriter(std::string indentation = "\t"); - ~StyledStreamWriter() {} - -public: - /** \brief Serialize a Value in JSON format. - * \param out Stream to write to. (Can be ostringstream, e.g.) - * \param root Value to serialize. - * \note There is no point in deriving from Writer, since write() should not - * return a value. - */ - void write(std::ostream& out, const Value& root); - -private: - void writeValue(const Value& value); - void writeArrayValue(const Value& value); - bool isMultineArray(const Value& value); - void pushValue(const std::string& value); - void writeIndent(); - void writeWithIndent(const std::string& value); - void indent(); - void unindent(); - void writeCommentBeforeValue(const Value& root); - void writeCommentAfterValueOnSameLine(const Value& root); - bool hasCommentForValue(const Value& value); - static std::string normalizeEOL(const std::string& text); - - typedef std::vector ChildValues; - - ChildValues childValues_; - std::ostream* document_; - std::string indentString_; - int rightMargin_; - std::string indentation_; - bool addChildValues_; -}; - -#if defined(JSON_HAS_INT64) -std::string JSON_API valueToString(Int value); -std::string JSON_API valueToString(UInt value); -#endif // if defined(JSON_HAS_INT64) -std::string JSON_API valueToString(LargestInt value); -std::string JSON_API valueToString(LargestUInt value); -std::string JSON_API valueToString(double value); -std::string JSON_API valueToString(bool value); -std::string JSON_API valueToQuotedString(const char* value); - -/// \brief Output using the StyledStreamWriter. -/// \see Json::operator>>() -JSON_API std::ostream& operator<<(std::ostream&, const Value& root); - -} // namespace Json - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // JSON_WRITER_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/writer.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/assertions.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED -#define CPPTL_JSON_ASSERTIONS_H_INCLUDED - -#include - -#if !defined(JSON_IS_AMALGAMATION) -#include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -#if JSON_USE_EXCEPTION -#include -#define JSON_ASSERT(condition) \ - assert(condition); // @todo <= change this into an exception throw -#define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message); -#else // JSON_USE_EXCEPTION -#define JSON_ASSERT(condition) assert(condition); - -// The call to assert() will show the failure message in debug builds. In -// release bugs we write to invalid memory in order to crash hard, so that a -// debugger or crash reporter gets the chance to take over. We still call exit() -// afterward in order to tell the compiler that this macro doesn't return. -#define JSON_FAIL_MESSAGE(message) \ - { \ - assert(false&& message); \ - strcpy(reinterpret_cast(666), message); \ - exit(123); \ - } - -#endif - -#define JSON_ASSERT_MESSAGE(condition, message) \ - if (!(condition)) { \ - JSON_FAIL_MESSAGE(message) \ - } - -#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/assertions.h -// ////////////////////////////////////////////////////////////////////// - - - - - -#endif //ifndef JSON_AMALGATED_H_INCLUDED - -#ifndef INCLUDE_CPP -#define INCLUDE_CPP -#include "../jsoncpp.cpp" +/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/). +/// It is intented to be used with #include + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is +released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur + +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. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + +#ifndef JSON_AMALGATED_H_INCLUDED +# define JSON_AMALGATED_H_INCLUDED +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +#define JSON_IS_AMALGAMATION + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/version.h +// ////////////////////////////////////////////////////////////////////// + +// DO NOT EDIT. This file is generated by CMake from "version" +// and "version.h.in" files. +// Run CMake configure step to update it. +#ifndef JSON_VERSION_H_INCLUDED +# define JSON_VERSION_H_INCLUDED + +# define JSONCPP_VERSION_STRING "0.7.0" +# define JSONCPP_VERSION_MAJOR 0 +# define JSONCPP_VERSION_MINOR 7 +# define JSONCPP_VERSION_PATCH 0 +# define JSONCPP_VERSION_QUALIFIER +# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) + +#endif // JSON_VERSION_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/version.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +#define JSON_CONFIG_H_INCLUDED + +/// If defined, indicates that json library is embedded in CppTL library. +//# define JSON_IN_CPPTL 1 + +/// If defined, indicates that json may leverage CppTL library +//# define JSON_USE_CPPTL 1 +/// If defined, indicates that cpptl vector based map should be used instead of +/// std::map +/// as Value container. +//# define JSON_USE_CPPTL_SMALLMAP 1 +/// If defined, indicates that Json specific container should be used +/// (hash table & simple deque container with customizable allocator). +/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 +//# define JSON_VALUE_USE_INTERNAL_MAP 1 +/// Force usage of standard new/malloc based allocator instead of memory pool +/// based allocator. +/// The memory pools allocator used optimization (initializing Value and +/// ValueInternalLink +/// as if it was a POD) that may cause some validation tool to report errors. +/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. +//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 + +// If non-zero, the library uses exceptions to report bad input instead of C +// assertion macros. The default is to use exceptions. +#ifndef JSON_USE_EXCEPTION +#define JSON_USE_EXCEPTION 1 +#endif + +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgated header. +// #define JSON_IS_AMALGAMATION + +#ifdef JSON_IN_CPPTL +#include +#ifndef JSON_USE_CPPTL +#define JSON_USE_CPPTL 1 +#endif +#endif + +#ifdef JSON_IN_CPPTL +#define JSON_API CPPTL_API +#elif defined(JSON_DLL_BUILD) +#if defined(_MSC_VER) +#define JSON_API __declspec(dllexport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#elif defined(JSON_DLL) +#if defined(_MSC_VER) +#define JSON_API __declspec(dllimport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#endif // ifdef JSON_IN_CPPTL +#if !defined(JSON_API) +#define JSON_API +#endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 +// Microsoft Visual Studio 6 only support conversion from __int64 to double +// (no conversion from unsigned __int64). +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' +// characters in the debug information) +// All projects I've ever seen with VS6 were using this globally (not bothering +// with pragma push/pop). +#pragma warning(disable : 4786) +#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 + +#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 +/// Indicates that the following function is deprecated. +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#endif + +#if !defined(JSONCPP_DEPRECATED) +#define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +namespace Json { +typedef int Int; +typedef unsigned int UInt; +#if defined(JSON_NO_INT64) +typedef int LargestInt; +typedef unsigned int LargestUInt; +#undef JSON_HAS_INT64 +#else // if defined(JSON_NO_INT64) +// For Microsoft Visual use specific types as long long is not supported +#if defined(_MSC_VER) // Microsoft Visual Studio +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else // if defined(_MSC_VER) // Other platforms, use long long +typedef long long int Int64; +typedef unsigned long long int UInt64; +#endif // if defined(_MSC_VER) +typedef Int64 LargestInt; +typedef UInt64 LargestUInt; +#define JSON_HAS_INT64 +#endif // if defined(JSON_NO_INT64) +} // end namespace Json + +#endif // JSON_CONFIG_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +#define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// writer.h +class FastWriter; +class StyledWriter; + +// reader.h +class Reader; + +// features.h +class Features; + +// value.h +typedef unsigned int ArrayIndex; +class StaticString; +class Path; +class PathArgument; +class Value; +class ValueIteratorBase; +class ValueIterator; +class ValueConstIterator; +#ifdef JSON_VALUE_USE_INTERNAL_MAP +class ValueMapAllocator; +class ValueInternalLink; +class ValueInternalArray; +class ValueInternalMap; +#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP + +} // namespace Json + +#endif // JSON_FORWARDS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/features.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_FEATURES_H_INCLUDED +#define CPPTL_JSON_FEATURES_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +/** \brief Configuration passed to reader and writer. + * This configuration object can be used to force the Reader or Writer + * to behave in a standard conforming way. + */ +class JSON_API Features { +public: + /** \brief A configuration that allows all features and assumes all strings + * are UTF-8. + * - C & C++ comments are allowed + * - Root object can be any JSON value + * - Assumes Value strings are encoded in UTF-8 + */ + static Features all(); + + /** \brief A configuration that is strictly compatible with the JSON + * specification. + * - Comments are forbidden. + * - Root object must be either an array or an object value. + * - Assumes Value strings are encoded in UTF-8 + */ + static Features strictMode(); + + /** \brief Initialize the configuration like JsonConfig::allFeatures; + */ + Features(); + + /// \c true if comments are allowed. Default: \c true. + bool allowComments_; + + /// \c true if root must be either an array or an object value. Default: \c + /// false. + bool strictRoot_; + + /// \c true if dropped null placeholders are allowed. Default: \c false. + bool allowDroppedNullPlaceholders_; + + /// \c true if numeric object key are allowed. Default: \c false. + bool allowNumericKeys_; +}; + +} // namespace Json + +#endif // CPPTL_JSON_FEATURES_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/features.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/value.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_H_INCLUDED +#define CPPTL_JSON_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include + +#ifndef JSON_USE_CPPTL_SMALLMAP +#include +#else +#include +#endif +#ifdef JSON_USE_CPPTL +#include +#endif + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +/** \brief JSON (JavaScript Object Notation). + */ +namespace Json { + +/** \brief Type of the value held by a Value object. + */ +enum ValueType { + nullValue = 0, ///< 'null' value + intValue, ///< signed integer value + uintValue, ///< unsigned integer value + realValue, ///< double value + stringValue, ///< UTF-8 string value + booleanValue, ///< bool value + arrayValue, ///< array value (ordered list) + objectValue ///< object value (collection of name/value pairs). +}; + +enum CommentPlacement { + commentBefore = 0, ///< a comment placed on the line before a value + commentAfterOnSameLine, ///< a comment just after a value on the same line + commentAfter, ///< a comment on the line after a value (only make sense for + /// root value) + numberOfCommentPlacement +}; + +//# ifdef JSON_USE_CPPTL +// typedef CppTL::AnyEnumerator EnumMemberNames; +// typedef CppTL::AnyEnumerator EnumValues; +//# endif + +/** \brief Lightweight wrapper to tag static string. + * + * Value constructor and objectValue member assignement takes advantage of the + * StaticString and avoid the cost of string duplication when storing the + * string or the member name. + * + * Example of usage: + * \code + * Json::Value aValue( StaticString("some text") ); + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ +class JSON_API StaticString { +public: + explicit StaticString(const char* czstring) : str_(czstring) {} + + operator const char*() const { return str_; } + + const char* c_str() const { return str_; } + +private: + const char* str_; +}; + +/** \brief Represents a JSON value. + * + * This class is a discriminated union wrapper that can represents a: + * - signed integer [range: Value::minInt - Value::maxInt] + * - unsigned integer (range: 0 - Value::maxUInt) + * - double + * - UTF-8 string + * - boolean + * - 'null' + * - an ordered list of Value + * - collection of name/value pairs (javascript object) + * + * The type of the held value is represented by a #ValueType and + * can be obtained using type(). + * + * values of an #objectValue or #arrayValue can be accessed using operator[]() + *methods. + * Non const methods will automatically create the a #nullValue element + * if it does not exist. + * The sequence of an #arrayValue will be automatically resize and initialized + * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. + * + * The get() methods can be used to obtanis default value in the case the + *required element + * does not exist. + * + * It is possible to iterate over the list of a #objectValue values using + * the getMemberNames() method. + */ +class JSON_API Value { + friend class ValueIteratorBase; +#ifdef JSON_VALUE_USE_INTERNAL_MAP + friend class ValueInternalLink; + friend class ValueInternalMap; +#endif +public: + typedef std::vector Members; + typedef ValueIterator iterator; + typedef ValueConstIterator const_iterator; + typedef Json::UInt UInt; + typedef Json::Int Int; +#if defined(JSON_HAS_INT64) + typedef Json::UInt64 UInt64; + typedef Json::Int64 Int64; +#endif // defined(JSON_HAS_INT64) + typedef Json::LargestInt LargestInt; + typedef Json::LargestUInt LargestUInt; + typedef Json::ArrayIndex ArrayIndex; + + static const Value& null; + /// Minimum signed integer value that can be stored in a Json::Value. + static const LargestInt minLargestInt; + /// Maximum signed integer value that can be stored in a Json::Value. + static const LargestInt maxLargestInt; + /// Maximum unsigned integer value that can be stored in a Json::Value. + static const LargestUInt maxLargestUInt; + + /// Minimum signed int value that can be stored in a Json::Value. + static const Int minInt; + /// Maximum signed int value that can be stored in a Json::Value. + static const Int maxInt; + /// Maximum unsigned int value that can be stored in a Json::Value. + static const UInt maxUInt; + +#if defined(JSON_HAS_INT64) + /// Minimum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 minInt64; + /// Maximum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 maxInt64; + /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. + static const UInt64 maxUInt64; +#endif // defined(JSON_HAS_INT64) + +private: +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION +#ifndef JSON_VALUE_USE_INTERNAL_MAP + class CZString { + public: + enum DuplicationPolicy { + noDuplication = 0, + duplicate, + duplicateOnCopy + }; + CZString(ArrayIndex index); + CZString(const char* cstr, DuplicationPolicy allocate); + CZString(const CZString& other); + ~CZString(); + CZString& operator=(CZString other); + bool operator<(const CZString& other) const; + bool operator==(const CZString& other) const; + ArrayIndex index() const; + const char* c_str() const; + bool isStaticString() const; + + private: + void swap(CZString& other); + const char* cstr_; + ArrayIndex index_; + }; + +public: +#ifndef JSON_USE_CPPTL_SMALLMAP + typedef std::map ObjectValues; +#else + typedef CppTL::SmallMap ObjectValues; +#endif // ifndef JSON_USE_CPPTL_SMALLMAP +#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP +#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + +public: + /** \brief Create a default Value of the given type. + + This is a very useful constructor. + To create an empty array, pass arrayValue. + To create an empty object, pass objectValue. + Another Value can then be set to this one by assignment. +This is useful since clear() and resize() will not alter types. + + Examples: +\code +Json::Value null_value; // null +Json::Value arr_value(Json::arrayValue); // [] +Json::Value obj_value(Json::objectValue); // {} +\endcode + */ + Value(ValueType type = nullValue); + Value(Int value); + Value(UInt value); +#if defined(JSON_HAS_INT64) + Value(Int64 value); + Value(UInt64 value); +#endif // if defined(JSON_HAS_INT64) + Value(double value); + Value(const char* value); + Value(const char* beginValue, const char* endValue); + /** \brief Constructs a value from a static string. + + * Like other value string constructor but do not duplicate the string for + * internal storage. The given string must remain alive after the call to this + * constructor. + * Example of usage: + * \code + * Json::Value aValue( StaticString("some text") ); + * \endcode + */ + Value(const StaticString& value); + Value(const std::string& value); +#ifdef JSON_USE_CPPTL + Value(const CppTL::ConstString& value); +#endif + Value(bool value); + Value(const Value& other); + ~Value(); + + Value& operator=(Value other); + /// Swap values. + /// \note Currently, comments are intentionally not swapped, for + /// both logic and efficiency. + void swap(Value& other); + + ValueType type() const; + + bool operator<(const Value& other) const; + bool operator<=(const Value& other) const; + bool operator>=(const Value& other) const; + bool operator>(const Value& other) const; + + bool operator==(const Value& other) const; + bool operator!=(const Value& other) const; + + int compare(const Value& other) const; + + const char* asCString() const; + std::string asString() const; +#ifdef JSON_USE_CPPTL + CppTL::ConstString asConstString() const; +#endif + Int asInt() const; + UInt asUInt() const; +#if defined(JSON_HAS_INT64) + Int64 asInt64() const; + UInt64 asUInt64() const; +#endif // if defined(JSON_HAS_INT64) + LargestInt asLargestInt() const; + LargestUInt asLargestUInt() const; + float asFloat() const; + double asDouble() const; + bool asBool() const; + + bool isNull() const; + bool isBool() const; + bool isInt() const; + bool isInt64() const; + bool isUInt() const; + bool isUInt64() const; + bool isIntegral() const; + bool isDouble() const; + bool isNumeric() const; + bool isString() const; + bool isArray() const; + bool isObject() const; + + bool isConvertibleTo(ValueType other) const; + + /// Number of values in array or object + ArrayIndex size() const; + + /// \brief Return true if empty array, empty object, or null; + /// otherwise, false. + bool empty() const; + + /// Return isNull() + bool operator!() const; + + /// Remove all object members and array elements. + /// \pre type() is arrayValue, objectValue, or nullValue + /// \post type() is unchanged + void clear(); + + /// Resize the array to size elements. + /// New elements are initialized to null. + /// May only be called on nullValue or arrayValue. + /// \pre type() is arrayValue or nullValue + /// \post type() is arrayValue + void resize(ArrayIndex size); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are + /// inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](ArrayIndex index); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are + /// inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](int index); + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](ArrayIndex index) const; + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](int index) const; + + /// If the array contains at least index+1 elements, returns the element + /// value, + /// otherwise returns defaultValue. + Value get(ArrayIndex index, const Value& defaultValue) const; + /// Return true if index < size(). + bool isValidIndex(ArrayIndex index) const; + /// \brief Append value to array at the end. + /// + /// Equivalent to jsonvalue[jsonvalue.size()] = value; + Value& append(const Value& value); + + /// Access an object value by name, create a null member if it does not exist. + Value& operator[](const char* key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const char* key) const; + /// Access an object value by name, create a null member if it does not exist. + Value& operator[](const std::string& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const std::string& key) const; + /** \brief Access an object value by name, create a null member if it does not + exist. + + * If the object as no entry for that name, then the member name used to store + * the new entry is not duplicated. + * Example of use: + * \code + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ + Value& operator[](const StaticString& key); +#ifdef JSON_USE_CPPTL + /// Access an object value by name, create a null member if it does not exist. + Value& operator[](const CppTL::ConstString& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const CppTL::ConstString& key) const; +#endif + /// Return the member named key if it exist, defaultValue otherwise. + Value get(const char* key, const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + Value get(const std::string& key, const Value& defaultValue) const; +#ifdef JSON_USE_CPPTL + /// Return the member named key if it exist, defaultValue otherwise. + Value get(const CppTL::ConstString& key, const Value& defaultValue) const; +#endif + /// \brief Remove and return the named member. + /// + /// Do nothing if it did not exist. + /// \return the removed Value, or null. + /// \pre type() is objectValue or nullValue + /// \post type() is unchanged + Value removeMember(const char* key); + /// Same as removeMember(const char*) + Value removeMember(const std::string& key); + + /// Return true if the object has a member named key. + bool isMember(const char* key) const; + /// Return true if the object has a member named key. + bool isMember(const std::string& key) const; +#ifdef JSON_USE_CPPTL + /// Return true if the object has a member named key. + bool isMember(const CppTL::ConstString& key) const; +#endif + + /// \brief Return a list of the member names. + /// + /// If null, return an empty list. + /// \pre type() is objectValue or nullValue + /// \post if type() was nullValue, it remains nullValue + Members getMemberNames() const; + + //# ifdef JSON_USE_CPPTL + // EnumMemberNames enumMemberNames() const; + // EnumValues enumValues() const; + //# endif + + /// Comments must be //... or /* ... */ + void setComment(const char* comment, CommentPlacement placement); + /// Comments must be //... or /* ... */ + void setComment(const std::string& comment, CommentPlacement placement); + bool hasComment(CommentPlacement placement) const; + /// Include delimiters and embedded newlines. + std::string getComment(CommentPlacement placement) const; + + std::string toStyledString() const; + + const_iterator begin() const; + const_iterator end() const; + + iterator begin(); + iterator end(); + + // Accessors for the [start, limit) range of bytes within the JSON text from + // which this value was parsed, if any. + void setOffsetStart(size_t start); + void setOffsetLimit(size_t limit); + size_t getOffsetStart() const; + size_t getOffsetLimit() const; + +private: + Value& resolveReference(const char* key, bool isStatic); + +#ifdef JSON_VALUE_USE_INTERNAL_MAP + inline bool isItemAvailable() const { return itemIsUsed_ == 0; } + + inline void setItemUsed(bool isUsed = true) { itemIsUsed_ = isUsed ? 1 : 0; } + + inline bool isMemberNameStatic() const { return memberNameIsStatic_ == 0; } + + inline void setMemberNameIsStatic(bool isStatic) { + memberNameIsStatic_ = isStatic ? 1 : 0; + } +#endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP + +private: + struct CommentInfo { + CommentInfo(); + ~CommentInfo(); + + void setComment(const char* text); + + char* comment_; + }; + + // struct MemberNamesTransform + //{ + // typedef const char *result_type; + // const char *operator()( const CZString &name ) const + // { + // return name.c_str(); + // } + //}; + + union ValueHolder { + LargestInt int_; + LargestUInt uint_; + double real_; + bool bool_; + char* string_; +#ifdef JSON_VALUE_USE_INTERNAL_MAP + ValueInternalArray* array_; + ValueInternalMap* map_; +#else + ObjectValues* map_; +#endif + } value_; + ValueType type_ : 8; + int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. +#ifdef JSON_VALUE_USE_INTERNAL_MAP + unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. + int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. +#endif + CommentInfo* comments_; + + // [start, limit) byte offsets in the source JSON text from which this Value + // was extracted. + size_t start_; + size_t limit_; +}; + +/** \brief Experimental and untested: represents an element of the "path" to + * access a node. + */ +class JSON_API PathArgument { +public: + friend class Path; + + PathArgument(); + PathArgument(ArrayIndex index); + PathArgument(const char* key); + PathArgument(const std::string& key); + +private: + enum Kind { + kindNone = 0, + kindIndex, + kindKey + }; + std::string key_; + ArrayIndex index_; + Kind kind_; +}; + +/** \brief Experimental and untested: represents a "path" to access a node. + * + * Syntax: + * - "." => root node + * - ".[n]" => elements at index 'n' of root node (an array value) + * - ".name" => member named 'name' of root node (an object value) + * - ".name1.name2.name3" + * - ".[0][1][2].name1[3]" + * - ".%" => member name is provided as parameter + * - ".[%]" => index is provied as parameter + */ +class JSON_API Path { +public: + Path(const std::string& path, + const PathArgument& a1 = PathArgument(), + const PathArgument& a2 = PathArgument(), + const PathArgument& a3 = PathArgument(), + const PathArgument& a4 = PathArgument(), + const PathArgument& a5 = PathArgument()); + + const Value& resolve(const Value& root) const; + Value resolve(const Value& root, const Value& defaultValue) const; + /// Creates the "path" to access the specified node and returns a reference on + /// the node. + Value& make(Value& root) const; + +private: + typedef std::vector InArgs; + typedef std::vector Args; + + void makePath(const std::string& path, const InArgs& in); + void addPathInArg(const std::string& path, + const InArgs& in, + InArgs::const_iterator& itInArg, + PathArgument::Kind kind); + void invalidPath(const std::string& path, int location); + + Args args_; +}; + +#ifdef JSON_VALUE_USE_INTERNAL_MAP +/** \brief Allocator to customize Value internal map. + * Below is an example of a simple implementation (default implementation + actually + * use memory pool for speed). + * \code + class DefaultValueMapAllocator : public ValueMapAllocator + { + public: // overridden from ValueMapAllocator + virtual ValueInternalMap *newMap() + { + return new ValueInternalMap(); + } + + virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) + { + return new ValueInternalMap( other ); + } + + virtual void destructMap( ValueInternalMap *map ) + { + delete map; + } + + virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) + { + return new ValueInternalLink[size]; + } + + virtual void releaseMapBuckets( ValueInternalLink *links ) + { + delete [] links; + } + + virtual ValueInternalLink *allocateMapLink() + { + return new ValueInternalLink(); + } + + virtual void releaseMapLink( ValueInternalLink *link ) + { + delete link; + } + }; + * \endcode + */ +class JSON_API ValueMapAllocator { +public: + virtual ~ValueMapAllocator(); + virtual ValueInternalMap* newMap() = 0; + virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) = 0; + virtual void destructMap(ValueInternalMap* map) = 0; + virtual ValueInternalLink* allocateMapBuckets(unsigned int size) = 0; + virtual void releaseMapBuckets(ValueInternalLink* links) = 0; + virtual ValueInternalLink* allocateMapLink() = 0; + virtual void releaseMapLink(ValueInternalLink* link) = 0; +}; + +/** \brief ValueInternalMap hash-map bucket chain link (for internal use only). + * \internal previous_ & next_ allows for bidirectional traversal. + */ +class JSON_API ValueInternalLink { +public: + enum { + itemPerLink = 6 + }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. + enum InternalFlags { + flagAvailable = 0, + flagUsed = 1 + }; + + ValueInternalLink(); + + ~ValueInternalLink(); + + Value items_[itemPerLink]; + char* keys_[itemPerLink]; + ValueInternalLink* previous_; + ValueInternalLink* next_; +}; + +/** \brief A linked page based hash-table implementation used internally by + *Value. + * \internal ValueInternalMap is a tradional bucket based hash-table, with a + *linked + * list in each bucket to handle collision. There is an addional twist in that + * each node of the collision linked list is a page containing a fixed amount of + * value. This provides a better compromise between memory usage and speed. + * + * Each bucket is made up of a chained list of ValueInternalLink. The last + * link of a given bucket can be found in the 'previous_' field of the following + *bucket. + * The last link of the last bucket is stored in tailLink_ as it has no + *following bucket. + * Only the last link of a bucket may contains 'available' item. The last link + *always + * contains at least one element unless is it the bucket one very first link. + */ +class JSON_API ValueInternalMap { + friend class ValueIteratorBase; + friend class Value; + +public: + typedef unsigned int HashKey; + typedef unsigned int BucketIndex; + +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + struct IteratorState { + IteratorState() : map_(0), link_(0), itemIndex_(0), bucketIndex_(0) {} + ValueInternalMap* map_; + ValueInternalLink* link_; + BucketIndex itemIndex_; + BucketIndex bucketIndex_; + }; +#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + + ValueInternalMap(); + ValueInternalMap(const ValueInternalMap& other); + ValueInternalMap& operator=(ValueInternalMap other); + ~ValueInternalMap(); + + void swap(ValueInternalMap& other); + + BucketIndex size() const; + + void clear(); + + bool reserveDelta(BucketIndex growth); + + bool reserve(BucketIndex newItemCount); + + const Value* find(const char* key) const; + + Value* find(const char* key); + + Value& resolveReference(const char* key, bool isStatic); + + void remove(const char* key); + + void doActualRemove(ValueInternalLink* link, + BucketIndex index, + BucketIndex bucketIndex); + + ValueInternalLink*& getLastLinkInBucket(BucketIndex bucketIndex); + + Value& setNewItem(const char* key, + bool isStatic, + ValueInternalLink* link, + BucketIndex index); + + Value& unsafeAdd(const char* key, bool isStatic, HashKey hashedKey); + + HashKey hash(const char* key) const; + + int compare(const ValueInternalMap& other) const; + +private: + void makeBeginIterator(IteratorState& it) const; + void makeEndIterator(IteratorState& it) const; + static bool equals(const IteratorState& x, const IteratorState& other); + static void increment(IteratorState& iterator); + static void incrementBucket(IteratorState& iterator); + static void decrement(IteratorState& iterator); + static const char* key(const IteratorState& iterator); + static const char* key(const IteratorState& iterator, bool& isStatic); + static Value& value(const IteratorState& iterator); + static int distance(const IteratorState& x, const IteratorState& y); + +private: + ValueInternalLink* buckets_; + ValueInternalLink* tailLink_; + BucketIndex bucketsSize_; + BucketIndex itemCount_; +}; + +/** \brief A simplified deque implementation used internally by Value. +* \internal +* It is based on a list of fixed "page", each page contains a fixed number of +*items. +* Instead of using a linked-list, a array of pointer is used for fast item +*look-up. +* Look-up for an element is as follow: +* - compute page index: pageIndex = itemIndex / itemsPerPage +* - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] +* +* Insertion is amortized constant time (only the array containing the index of +*pointers +* need to be reallocated when items are appended). +*/ +class JSON_API ValueInternalArray { + friend class Value; + friend class ValueIteratorBase; + +public: + enum { + itemsPerPage = 8 + }; // should be a power of 2 for fast divide and modulo. + typedef Value::ArrayIndex ArrayIndex; + typedef unsigned int PageIndex; + +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + struct IteratorState // Must be a POD + { + IteratorState() : array_(0), currentPageIndex_(0), currentItemIndex_(0) {} + ValueInternalArray* array_; + Value** currentPageIndex_; + unsigned int currentItemIndex_; + }; +#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + + ValueInternalArray(); + ValueInternalArray(const ValueInternalArray& other); + ValueInternalArray& operator=(ValueInternalArray other); + ~ValueInternalArray(); + void swap(ValueInternalArray& other); + + void clear(); + void resize(ArrayIndex newSize); + + Value& resolveReference(ArrayIndex index); + + Value* find(ArrayIndex index) const; + + ArrayIndex size() const; + + int compare(const ValueInternalArray& other) const; + +private: + static bool equals(const IteratorState& x, const IteratorState& other); + static void increment(IteratorState& iterator); + static void decrement(IteratorState& iterator); + static Value& dereference(const IteratorState& iterator); + static Value& unsafeDereference(const IteratorState& iterator); + static int distance(const IteratorState& x, const IteratorState& y); + static ArrayIndex indexOf(const IteratorState& iterator); + void makeBeginIterator(IteratorState& it) const; + void makeEndIterator(IteratorState& it) const; + void makeIterator(IteratorState& it, ArrayIndex index) const; + + void makeIndexValid(ArrayIndex index); + + Value** pages_; + ArrayIndex size_; + PageIndex pageCount_; +}; + +/** \brief Experimental: do not use. Allocator to customize Value internal +array. + * Below is an example of a simple implementation (actual implementation use + * memory pool). + \code +class DefaultValueArrayAllocator : public ValueArrayAllocator +{ +public: // overridden from ValueArrayAllocator +virtual ~DefaultValueArrayAllocator() +{ +} + +virtual ValueInternalArray *newArray() +{ + return new ValueInternalArray(); +} + +virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) +{ + return new ValueInternalArray( other ); +} + +virtual void destruct( ValueInternalArray *array ) +{ + delete array; +} + +virtual void reallocateArrayPageIndex( Value **&indexes, + ValueInternalArray::PageIndex +&indexCount, + ValueInternalArray::PageIndex +minNewIndexCount ) +{ + ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; + if ( minNewIndexCount > newIndexCount ) + newIndexCount = minNewIndexCount; + void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); + if ( !newIndexes ) + throw std::bad_alloc(); + indexCount = newIndexCount; + indexes = static_cast( newIndexes ); +} +virtual void releaseArrayPageIndex( Value **indexes, + ValueInternalArray::PageIndex indexCount ) +{ + if ( indexes ) + free( indexes ); +} + +virtual Value *allocateArrayPage() +{ + return static_cast( malloc( sizeof(Value) * +ValueInternalArray::itemsPerPage ) ); +} + +virtual void releaseArrayPage( Value *value ) +{ + if ( value ) + free( value ); +} +}; + \endcode + */ +class JSON_API ValueArrayAllocator { +public: + virtual ~ValueArrayAllocator(); + virtual ValueInternalArray* newArray() = 0; + virtual ValueInternalArray* newArrayCopy(const ValueInternalArray& other) = 0; + virtual void destructArray(ValueInternalArray* array) = 0; + /** \brief Reallocate array page index. + * Reallocates an array of pointer on each page. + * \param indexes [input] pointer on the current index. May be \c NULL. + * [output] pointer on the new index of at least + * \a minNewIndexCount pages. + * \param indexCount [input] current number of pages in the index. + * [output] number of page the reallocated index can handle. + * \b MUST be >= \a minNewIndexCount. + * \param minNewIndexCount Minimum number of page the new index must be able + * to + * handle. + */ + virtual void + reallocateArrayPageIndex(Value**& indexes, + ValueInternalArray::PageIndex& indexCount, + ValueInternalArray::PageIndex minNewIndexCount) = 0; + virtual void + releaseArrayPageIndex(Value** indexes, + ValueInternalArray::PageIndex indexCount) = 0; + virtual Value* allocateArrayPage() = 0; + virtual void releaseArrayPage(Value* value) = 0; +}; +#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP + +/** \brief base class for Value iterators. + * + */ +class JSON_API ValueIteratorBase { +public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef unsigned int size_t; + typedef int difference_type; + typedef ValueIteratorBase SelfType; + + ValueIteratorBase(); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); +#else + ValueIteratorBase(const ValueInternalArray::IteratorState& state); + ValueIteratorBase(const ValueInternalMap::IteratorState& state); +#endif + + bool operator==(const SelfType& other) const { return isEqual(other); } + + bool operator!=(const SelfType& other) const { return !isEqual(other); } + + difference_type operator-(const SelfType& other) const { + return computeDistance(other); + } + + /// Return either the index or the member name of the referenced value as a + /// Value. + Value key() const; + + /// Return the index of the referenced Value. -1 if it is not an arrayValue. + UInt index() const; + + /// Return the member name of the referenced Value. "" if it is not an + /// objectValue. + const char* memberName() const; + +protected: + Value& deref() const; + + void increment(); + + void decrement(); + + difference_type computeDistance(const SelfType& other) const; + + bool isEqual(const SelfType& other) const; + + void copy(const SelfType& other); + +private: +#ifndef JSON_VALUE_USE_INTERNAL_MAP + Value::ObjectValues::iterator current_; + // Indicates that iterator is for a null value. + bool isNull_; +#else + union { + ValueInternalArray::IteratorState array_; + ValueInternalMap::IteratorState map_; + } iterator_; + bool isArray_; +#endif +}; + +/** \brief const iterator for object and array value. + * + */ +class JSON_API ValueConstIterator : public ValueIteratorBase { + friend class Value; + +public: + typedef const Value value_type; + typedef unsigned int size_t; + typedef int difference_type; + typedef const Value& reference; + typedef const Value* pointer; + typedef ValueConstIterator SelfType; + + ValueConstIterator(); + +private: +/*! \internal Use by Value to create an iterator. + */ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + explicit ValueConstIterator(const Value::ObjectValues::iterator& current); +#else + ValueConstIterator(const ValueInternalArray::IteratorState& state); + ValueConstIterator(const ValueInternalMap::IteratorState& state); +#endif +public: + SelfType& operator=(const ValueIteratorBase& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +/** \brief Iterator for object and array value. + */ +class JSON_API ValueIterator : public ValueIteratorBase { + friend class Value; + +public: + typedef Value value_type; + typedef unsigned int size_t; + typedef int difference_type; + typedef Value& reference; + typedef Value* pointer; + typedef ValueIterator SelfType; + + ValueIterator(); + ValueIterator(const ValueConstIterator& other); + ValueIterator(const ValueIterator& other); + +private: +/*! \internal Use by Value to create an iterator. + */ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + explicit ValueIterator(const Value::ObjectValues::iterator& current); +#else + ValueIterator(const ValueInternalArray::IteratorState& state); + ValueIterator(const ValueInternalMap::IteratorState& state); +#endif +public: + SelfType& operator=(const SelfType& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +} // namespace Json + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // CPPTL_JSON_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/value.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/reader.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_READER_H_INCLUDED +#define CPPTL_JSON_READER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "features.h" +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +namespace Json { + +/** \brief Unserialize a JSON document into a + *Value. + * + */ +class JSON_API Reader { +public: + typedef char Char; + typedef const Char* Location; + + /** \brief An error tagged with where in the JSON text it was encountered. + * + * The offsets give the [start, limit) range of bytes within the text. Note + * that this is bytes, not codepoints. + * + */ + struct StructuredError { + size_t offset_start; + size_t offset_limit; + std::string message; + }; + + /** \brief Constructs a Reader allowing all features + * for parsing. + */ + Reader(); + + /** \brief Constructs a Reader allowing the specified feature set + * for parsing. + */ + Reader(const Features& features); + + /** \brief Read a Value from a JSON + * document. + * \param document UTF-8 encoded string containing the document to read. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param collectComments \c true to collect comment and allow writing them + * back during + * serialization, \c false to discard comments. + * This parameter is ignored if + * Features::allowComments_ + * is \c false. + * \return \c true if the document was successfully parsed, \c false if an + * error occurred. + */ + bool + parse(const std::string& document, Value& root, bool collectComments = true); + + /** \brief Read a Value from a JSON + document. + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the + document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the + document to read. + \ Must be >= beginDoc. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param collectComments \c true to collect comment and allow writing them + back during + * serialization, \c false to discard comments. + * This parameter is ignored if + Features::allowComments_ + * is \c false. + * \return \c true if the document was successfully parsed, \c false if an + error occurred. + */ + bool parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments = true); + + /// \brief Parse from input stream. + /// \see Json::operator>>(std::istream&, Json::Value&). + bool parse(std::istream& is, Value& root, bool collectComments = true); + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * \return Formatted error message with the list of errors with their location + * in + * the parsed document. An empty string is returned if no error + * occurred + * during parsing. + * \deprecated Use getFormattedErrorMessages() instead (typo fix). + */ + JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") + std::string getFormatedErrorMessages() const; + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * \return Formatted error message with the list of errors with their location + * in + * the parsed document. An empty string is returned if no error + * occurred + * during parsing. + */ + std::string getFormattedErrorMessages() const; + + /** \brief Returns a vector of structured erros encounted while parsing. + * \return A (possibly empty) vector of StructuredError objects. Currently + * only one error can be returned, but the caller should tolerate + * multiple + * errors. This can occur if the parser recovers from a non-fatal + * parse error and then encounters additional errors. + */ + std::vector getStructuredErrors() const; + +private: + enum TokenType { + tokenEndOfStream = 0, + tokenObjectBegin, + tokenObjectEnd, + tokenArrayBegin, + tokenArrayEnd, + tokenString, + tokenNumber, + tokenTrue, + tokenFalse, + tokenNull, + tokenArraySeparator, + tokenMemberSeparator, + tokenComment, + tokenError + }; + + class Token { + public: + TokenType type_; + Location start_; + Location end_; + }; + + class ErrorInfo { + public: + Token token_; + std::string message_; + Location extra_; + }; + + typedef std::deque Errors; + + bool expectToken(TokenType type, Token& token, const char* message); + bool readToken(Token& token); + void skipSpaces(); + bool match(Location pattern, int patternLength); + bool readComment(); + bool readCStyleComment(); + bool readCppStyleComment(); + bool readString(); + void readNumber(); + bool readValue(); + bool readObject(Token& token); + bool readArray(Token& token); + bool decodeNumber(Token& token); + bool decodeNumber(Token& token, Value& decoded); + bool decodeString(Token& token); + bool decodeString(Token& token, std::string& decoded); + bool decodeDouble(Token& token); + bool decodeDouble(Token& token, Value& decoded); + bool decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode); + bool addError(const std::string& message, Token& token, Location extra = 0); + bool recoverFromError(TokenType skipUntilToken); + bool addErrorAndRecover(const std::string& message, + Token& token, + TokenType skipUntilToken); + void skipUntilSpace(); + Value& currentValue(); + Char getNextChar(); + void + getLocationLineAndColumn(Location location, int& line, int& column) const; + std::string getLocationLineAndColumn(Location location) const; + void addComment(Location begin, Location end, CommentPlacement placement); + void skipCommentTokens(Token& token); + + typedef std::stack Nodes; + Nodes nodes_; + Errors errors_; + std::string document_; + Location begin_; + Location end_; + Location current_; + Location lastValueEnd_; + Value* lastValue_; + std::string commentsBefore_; + Features features_; + bool collectComments_; +}; + +/** \brief Read from 'sin' into 'root'. + + Always keep comments from the input JSON. + + This can be used to read a file into a particular sub-object. + For example: + \code + Json::Value root; + cin >> root["dir"]["file"]; + cout << root; + \endcode + Result: + \verbatim + { + "dir": { + "file": { + // The input stream JSON would be nested here. + } + } + } + \endverbatim + \throw std::exception on parse error. + \see Json::operator<<() +*/ +JSON_API std::istream& operator>>(std::istream&, Value&); + +} // namespace Json + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // CPPTL_JSON_READER_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/reader.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/writer.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_WRITER_H_INCLUDED +#define JSON_WRITER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +namespace Json { + +class Value; + +/** \brief Abstract class for writers. + */ +class JSON_API Writer { +public: + virtual ~Writer(); + + virtual std::string write(const Value& root) = 0; +}; + +/** \brief Outputs a Value in JSON format + *without formatting (not human friendly). + * + * The JSON document is written in a single line. It is not intended for 'human' + *consumption, + * but may be usefull to support feature such as RPC where bandwith is limited. + * \sa Reader, Value + */ +class JSON_API FastWriter : public Writer { +public: + FastWriter(); + virtual ~FastWriter() {} + + void enableYAMLCompatibility(); + + /** \brief Drop the "null" string from the writer's output for nullValues. + * Strictly speaking, this is not valid JSON. But when the output is being + * fed to a browser's Javascript, it makes for smaller output and the + * browser can handle the output just fine. + */ + void dropNullPlaceholders(); + + void omitEndingLineFeed(); + +public: // overridden from Writer + virtual std::string write(const Value& root); + +private: + void writeValue(const Value& value); + + std::string document_; + bool yamlCompatiblityEnabled_; + bool dropNullPlaceholders_; + bool omitEndingLineFeed_; +}; + +/** \brief Writes a Value in JSON format in a + *human friendly way. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + *line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + *types, + * and all the values fit on one lines, then print the array on a single + *line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + *#CommentPlacement. + * + * \sa Reader, Value, Value::setComment() + */ +class JSON_API StyledWriter : public Writer { +public: + StyledWriter(); + virtual ~StyledWriter() {} + +public: // overridden from Writer + /** \brief Serialize a Value in JSON format. + * \param root Value to serialize. + * \return String containing the JSON document that represents the root value. + */ + virtual std::string write(const Value& root); + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultineArray(const Value& value); + void pushValue(const std::string& value); + void writeIndent(); + void writeWithIndent(const std::string& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + bool hasCommentForValue(const Value& value); + static std::string normalizeEOL(const std::string& text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::string document_; + std::string indentString_; + int rightMargin_; + int indentSize_; + bool addChildValues_; +}; + +/** \brief Writes a Value in JSON format in a + human friendly way, + to a stream rather than to a string. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + types, + * and all the values fit on one lines, then print the array on a single + line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + #CommentPlacement. + * + * \param indentation Each level will be indented by this amount extra. + * \sa Reader, Value, Value::setComment() + */ +class JSON_API StyledStreamWriter { +public: + StyledStreamWriter(std::string indentation = "\t"); + ~StyledStreamWriter() {} + +public: + /** \brief Serialize a Value in JSON format. + * \param out Stream to write to. (Can be ostringstream, e.g.) + * \param root Value to serialize. + * \note There is no point in deriving from Writer, since write() should not + * return a value. + */ + void write(std::ostream& out, const Value& root); + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultineArray(const Value& value); + void pushValue(const std::string& value); + void writeIndent(); + void writeWithIndent(const std::string& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + bool hasCommentForValue(const Value& value); + static std::string normalizeEOL(const std::string& text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::ostream* document_; + std::string indentString_; + int rightMargin_; + std::string indentation_; + bool addChildValues_; +}; + +#if defined(JSON_HAS_INT64) +std::string JSON_API valueToString(Int value); +std::string JSON_API valueToString(UInt value); +#endif // if defined(JSON_HAS_INT64) +std::string JSON_API valueToString(LargestInt value); +std::string JSON_API valueToString(LargestUInt value); +std::string JSON_API valueToString(double value); +std::string JSON_API valueToString(bool value); +std::string JSON_API valueToQuotedString(const char* value); + +/// \brief Output using the StyledStreamWriter. +/// \see Json::operator>>() +JSON_API std::ostream& operator<<(std::ostream&, const Value& root); + +} // namespace Json + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // JSON_WRITER_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/writer.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/assertions.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED +#define CPPTL_JSON_ASSERTIONS_H_INCLUDED + +#include + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +#if JSON_USE_EXCEPTION +#include +#define JSON_ASSERT(condition) \ + assert(condition); // @todo <= change this into an exception throw +#define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message); +#else // JSON_USE_EXCEPTION +#define JSON_ASSERT(condition) assert(condition); + +// The call to assert() will show the failure message in debug builds. In +// release bugs we write to invalid memory in order to crash hard, so that a +// debugger or crash reporter gets the chance to take over. We still call exit() +// afterward in order to tell the compiler that this macro doesn't return. +#define JSON_FAIL_MESSAGE(message) \ + { \ + assert(false&& message); \ + strcpy(reinterpret_cast(666), message); \ + exit(123); \ + } + +#endif + +#define JSON_ASSERT_MESSAGE(condition, message) \ + if (!(condition)) { \ + JSON_FAIL_MESSAGE(message) \ + } + +#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/assertions.h +// ////////////////////////////////////////////////////////////////////// + + + + + +#endif //ifndef JSON_AMALGATED_H_INCLUDED + +#ifndef INCLUDE_CPP +#define INCLUDE_CPP +#include "../jsoncpp.cpp" #endif \ No newline at end of file diff --git a/cpp/log.h b/cpp/log.h new file mode 100644 index 0000000..a658f02 --- /dev/null +++ b/cpp/log.h @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +#include "reversi.h" + +using namespace std; + +struct node{ + board brd; + bool color; + short height, depth; + val_type alpha, beta; + val_type value; +}; +typedef const node& cnode; + +class log_record{ +protected: + bool flag; + vector vec; + +public: + log_record():flag(false){} + + void enable(){ + flag = true; + } + void disable(){ + flag = false; + } + void clear(){ + vec.clear(); + } + void insert(cnode n){ + if(flag){ + vec.push_back(n); + } + } + void save(const string& filename)const{ + ofstream out(filename, ios::binary | ios::out); + for(auto iter = vec.rbegin(); iter != vec.rend(); ++iter){ + out.write((const char*) &(*iter), sizeof(node)); + } + out.close(); + } +}; diff --git a/matrix.h b/cpp/matrix.h similarity index 100% rename from matrix.h rename to cpp/matrix.h diff --git a/pattern.cc b/cpp/pattern.cc similarity index 87% rename from pattern.cc rename to cpp/pattern.cc index 3b28ba9..0f45d56 100644 --- a/pattern.cc +++ b/cpp/pattern.cc @@ -40,7 +40,7 @@ const short pattern::table_num_convert[pattern::size][4] = { {32, 33, 34, 35} }; -const brd_type pattern::table_mask[pattern::size_n] = { +const ull pattern::table_mask[pattern::size_n] = { // horizontal pattern 0x00000000000000ff, 0x000000000000ff00, @@ -89,21 +89,21 @@ const brd_type pattern::table_mask[pattern::size_n] = { void get_index(cbool color, cboard brd, int* const& ind){ - brd_type brd_blue = brd.bget(color); - brd_type brd_green = brd.bget(!color); - brd_type brd_v_blue = brd_blue; - brd_type brd_v_green = brd_green; + ull brd_blue = brd.bget(color); + ull brd_green = brd.bget(!color); + ull brd_v_blue = brd_blue; + ull brd_v_green = brd_green; board::mirror_v(brd_v_blue); board::mirror_v(brd_v_green); - brd_type brd_h_blue = brd_blue; - brd_type brd_h_green = brd_green; + ull brd_h_blue = brd_blue; + ull brd_h_green = brd_green; board::mirror_h(brd_h_blue); board::mirror_h(brd_h_green); - brd_type brd_r_blue = brd_h_blue; - brd_type brd_r_green = brd_h_green; + ull brd_r_blue = brd_h_blue; + ull brd_r_green = brd_h_green; board::mirror_v(brd_r_blue); board::mirror_v(brd_r_green); - brd_type index; + ull index; //horizontal pattern index = 0 << 16; @@ -296,21 +296,21 @@ void get_index(cbool color, cboard brd, int* const& ind){ } float board::score_ptn(cbool color,const pattern& ptn)const{ - brd_type brd_blue = bget(color); - brd_type brd_green = bget(!color); - brd_type brd_v_blue = brd_blue; - brd_type brd_v_green = brd_green; + ull brd_blue = bget(color); + ull brd_green = bget(!color); + ull brd_v_blue = brd_blue; + ull brd_v_green = brd_green; mirror_v(brd_v_blue); mirror_v(brd_v_green); - brd_type brd_h_blue = brd_blue; - brd_type brd_h_green = brd_green; + ull brd_h_blue = brd_blue; + ull brd_h_green = brd_green; mirror_h(brd_h_blue); mirror_h(brd_h_green); - brd_type brd_r_blue = brd_h_blue; - brd_type brd_r_green = brd_h_green; + ull brd_r_blue = brd_h_blue; + ull brd_r_green = brd_h_green; mirror_v(brd_r_blue); mirror_v(brd_r_green); - brd_type index; + ull index; float result; result = 0; @@ -508,21 +508,21 @@ float board::score_ptn(cbool color,const pattern& ptn)const{ } void board::adjust_ptn(cbool color,pattern& ptn,cfloat value)const{ - brd_type brd_blue = bget(color); - brd_type brd_green = bget(!color); - brd_type brd_v_blue = brd_blue; - brd_type brd_v_green = brd_green; + ull brd_blue = bget(color); + ull brd_green = bget(!color); + ull brd_v_blue = brd_blue; + ull brd_v_green = brd_green; mirror_v(brd_v_blue); mirror_v(brd_v_green); - brd_type brd_h_blue = brd_blue; - brd_type brd_h_green = brd_green; + ull brd_h_blue = brd_blue; + ull brd_h_green = brd_green; mirror_h(brd_h_blue); mirror_h(brd_h_green); - brd_type brd_r_blue = brd_h_blue; - brd_type brd_r_green = brd_h_green; + ull brd_r_blue = brd_h_blue; + ull brd_r_green = brd_h_green; mirror_v(brd_r_blue); mirror_v(brd_r_green); - brd_type index; + ull index; //horizontal pattern index = 0 << 16; @@ -746,7 +746,7 @@ void group::load(istream& fin){ _READ(ptn_size); _READ(group_size); - if(calc_size != sizeof(calc_type)){ + if(calc_size != sizeof(val_type)){ cout << "Error: The size of element does not match." << endl; return; } @@ -781,7 +781,7 @@ void group::load(const string& path){ _READ(ptn_size); _READ(group_size); - if(calc_size != sizeof(calc_type)){ + if(calc_size != sizeof(val_type)){ fin.close(); cout << "Error: The size of element does not match." << endl; return; @@ -807,7 +807,7 @@ void group::save(const string& path)const{ #define WRITE(var) fout.write((const char *)(&var),sizeof(var)) ofstream fout(path,ios::out | ios::binary); - size_t calc_size = sizeof(calc_type); + size_t calc_size = sizeof(val_type); size_t ptn_size = sizeof(pattern); size_t group_size = vec.size(); @@ -831,7 +831,7 @@ void group::save(const string& path)const{ void pattern::balance(){ unsigned char index_l, index_h; int index; - calc_type value; + val_type value; #define balance_part(num) \ value = (table[(num << 16) | i] + table[(num << 16) | index]) / 2; \ @@ -855,10 +855,10 @@ void pattern::balance(){ balance_part(4); index_l = i; - asm_ror(index_l,1); + fun_ror(index_l,1); index_l = table_reverse[index_l]; index_h = i >> 8; - asm_ror(index_h,1); + fun_ror(index_h,1); index_h = table_reverse[index_h]; index = index_h; index <<= 8; @@ -867,10 +867,10 @@ void pattern::balance(){ balance_part(5); index_l = i; - asm_ror(index_l,2); + fun_ror(index_l,2); index_l = table_reverse[index_l]; index_h = i >> 8; - asm_ror(index_h,2); + fun_ror(index_h,2); index_h = table_reverse[index_h]; index = index_h; index <<= 8; @@ -879,10 +879,10 @@ void pattern::balance(){ balance_part(6); index_l = i; - asm_ror(index_l,3); + fun_ror(index_l,3); index_l = table_reverse[index_l]; index_h = i >> 8; - asm_ror(index_h,3); + fun_ror(index_h,3); index_h = table_reverse[index_h]; index = index_h; index <<= 8; @@ -891,10 +891,10 @@ void pattern::balance(){ balance_part(7); index_l = i; - asm_ror(index_l,4); + fun_ror(index_l,4); index_l = table_reverse[index_l]; index_h = i >> 8; - asm_ror(index_h,4); + fun_ror(index_h,4); index_h = table_reverse[index_h]; index = index_h; index <<= 8; @@ -903,9 +903,9 @@ void pattern::balance(){ balance_part(8); index_l = i; - asm_ror(index_l,4); + fun_ror(index_l,4); index_h = i >> 8; - asm_ror(index_h,4); + fun_ror(index_h,4); index = index_h; index <<= 8; index |= index_l; @@ -936,6 +936,7 @@ float mat_2f(const matrix& m){ return m.at(0); } +/* unordered_set sample_gen(cint n){ unordered_set brds; board brd,brd_save; @@ -961,6 +962,7 @@ unordered_set sample_gen(cint n){ return brds; }; + matrix sample_2mat(const unordered_set& brds){ int i = 0; matrix result(brds.size(),1); @@ -980,6 +982,7 @@ matrix sample_process(const unordered_set& brds){ } return result; } +*/ matrix correlate(const matrix& index1, const matrix& index2){ int h = index1.geth(), w = index2.geth(); @@ -1002,26 +1005,28 @@ matrix correlate(const matrix& index1, const matrix& index2){ return result; } -matrix evaluate(const unordered_set& brds,cmethod mthd,cshort height){ +/* +matrix evaluate(const unordered_set& brds,cmethod mthd,cshort height){ int i = 0; - matrix result(brds.size(),1); + matrix result(brds.size(),1); for(cboard brd:brds){ result.at(i) = brd.search(mthd,true,height); ++i; } return result; } +*/ -matrix evaluate(const matrix& brds,cmethod mthd,cshort height){ - matrix result(brds.geth(),1); +matrix evaluate(const matrix& brds,cmethod mthd,cshort height){ + matrix result(brds.geth(),1); for(int i = 0;i != brds.geth();++i){ result.at(i) = brds.at(i).search(mthd,true,height); } return result; } -matrix evaluate(const pattern& ptn, const matrix& index){ - matrix result(index.geth(),1); +matrix evaluate(const pattern& ptn, const matrix& index){ + matrix result(index.geth(),1); for(int i = 0;i != index.geth();++i){ result.at(i) = 0; for(int j = 0;j != index.getw();++j){ @@ -1031,8 +1036,8 @@ matrix evaluate(const pattern& ptn, const matrix& index){ return result; } -matrix evaluate(const pattern& ptn, const matrix& brds){ - matrix result(brds.geth(),1); +matrix evaluate(const pattern& ptn, const matrix& brds){ + matrix result(brds.geth(),1); for(int i = 0;i != brds.geth();++i){ result.at(i) = brds.at(i).score_ptn(true,ptn); @@ -1040,7 +1045,7 @@ matrix evaluate(const pattern& ptn, const matrix& brds){ return result; } -void adjust(pattern& ptn, const matrix& index, const matrix& delta){ +void adjust(pattern& ptn, const matrix& index, const matrix& delta){ for(int i = 0;i != index.geth();++i){ for(int j = 0;j != index.getw();++j){ ptn.at(index[i][j]) += delta.at(i); @@ -1048,47 +1053,8 @@ void adjust(pattern& ptn, const matrix& index, const matrix& del } } -void adjust(pattern& ptn, const matrix& brds, const matrix& delta){ +void adjust(pattern& ptn, const matrix& brds, const matrix& delta){ for(int i = 0;i != brds.geth();++i){ brds.at(i).adjust_ptn(true,ptn,delta.at(i)); } } - -bool is_prime(const long long& num){ - if(num <= 1) - return false; - int factor = 2; - int bound = sqrt(num); - for (;factor != 11 && factor <= bound;++factor){ - if (num % factor == 0) - return false; - } - factor = 11; - while(factor <= bound){ - if (num % factor == 0) - return false; - factor += 2; - if (num % factor == 0) - return false; - factor += 4; - if (num % factor == 0) - return false; - factor += 2; - if (num % factor == 0) - return false; - factor += 4; - if (num % factor == 0) - return false; - factor += 6; - if (num % factor == 0) - return false; - factor += 2; - if (num % factor == 0) - return false; - factor += 6; - if (num % factor == 0) - return false; - factor += 4; - } - return true; -} diff --git a/pattern.h b/cpp/pattern.h similarity index 69% rename from pattern.h rename to cpp/pattern.h index 048ac45..4c4367b 100644 --- a/pattern.h +++ b/cpp/pattern.h @@ -5,7 +5,6 @@ #include #include #include -#include #include "matrix.h" #include "type.h" @@ -37,16 +36,16 @@ class pattern{ static const short table_num[size_n]; static const short table_num_size[size]; static const short table_num_convert[size][4]; - static const brd_type table_mask[size_n]; + static const ull table_mask[size_n]; - calc_type table[size * length]; + val_type table[size * length]; void initial(){ memset(table,0,sizeof(table)); } static void config(){ - brd_type j = 0; - for(brd_type i = 0;i != length;++i){ + ull j = 0; + for(ull i = 0;i != length;++i){ if((i & (i >> 8)) == 0){ table_map[i] = j; table_map_inv[j] = i; @@ -56,9 +55,9 @@ class pattern{ } } - for(brd_type i = 0;i != 256;++i){ + for(ull i = 0;i != 256;++i){ j = board::deposit(i,0x0101010101010101); - asm_bswap(j); + board::mirror_v(j); j = board::extract(j,0x0101010101010101); table_reverse[i] = j; @@ -69,16 +68,16 @@ class pattern{ } } - calc_type& at(cint n,cint pos){ + val_type& at(cint n,cint pos){ return table[(n << 16) + pos]; }; - ccalc_type at(cint n,cint pos)const{ + cval_type at(cint n,cint pos)const{ return table[(n << 16) + pos]; }; - calc_type& at(cint n){ + val_type& at(cint n){ return table[n]; }; - ccalc_type at(cint n)const{ + cval_type at(cint n)const{ return table[n]; }; @@ -118,17 +117,15 @@ class group{ void get_index(cbool color, cboard brd, int* const& ind); matrix mat_i2f(const matrix& m); float mat_2f(const matrix& m); -matrix sample_2mat(const unordered_set& brds); -unordered_set sample_gen(cint n); -matrix sample_process(const unordered_set& brds); +//matrix sample_2mat(const unordered_set& brds); +//unordered_set sample_gen(cint n); +//matrix sample_process(const unordered_set& brds); matrix correlate(const matrix& index1, const matrix& index2); -matrix evaluate(const unordered_set& brds,cmethod mthd,cshort height); -matrix evaluate(const matrix& brds,cmethod mthd,cshort height); -matrix evaluate(const pattern& ptn, const matrix& index); -matrix evaluate(const pattern& ptn, const matrix& brds); -void adjust(pattern& ptn, const matrix& index, const matrix& delta); -void adjust(pattern& ptn, const matrix& brds, const matrix& delta); - -bool is_prime(const long long& num); +//matrix evaluate(const unordered_set& brds,cmethod mthd,cshort height); +matrix evaluate(const matrix& brds,cmethod mthd,cshort height); +matrix evaluate(const pattern& ptn, const matrix& index); +matrix evaluate(const pattern& ptn, const matrix& brds); +void adjust(pattern& ptn, const matrix& index, const matrix& delta); +void adjust(pattern& ptn, const matrix& brds, const matrix& delta); #endif //PATTERN_H diff --git a/cpp/reversi.cc b/cpp/reversi.cc new file mode 100644 index 0000000..a3ed983 --- /dev/null +++ b/cpp/reversi.cc @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include + +#include "reversi.h" +#include "search.h" + +default_random_engine engine( + chrono::system_clock::now().time_since_epoch().count() +); + +const pos_type board::size; +const pos_type board::size2; + +void board::print(ostream& out)const{ + string s = + "╔═╤═╤═╤═╤═╤═╤═╤═╗\n" + "║ │ │ │ │ │ │ │ ║\n" + "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" + "║ │ │ │ │ │ │ │ ║\n" + "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" + "║ │ │ │ │ │ │ │ ║\n" + "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" + "║ │ │ │ │ │ │ │ ║\n" + "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" + "║ │ │ │ │ │ │ │ ║\n" + "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" + "║ │ │ │ │ │ │ │ ║\n" + "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" + "║ │ │ │ │ │ │ │ ║\n" + "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" + "║ │ │ │ │ │ │ │ ║\n" + "╚═╧═╧═╧═╧═╧═╧═╧═╝\n" + ; + + pos_type pos = 0; + for(char& chr:s){ + if(chr == ' '){ + switch(get(pos)){ + case blank: + out << " "; + break; + case black: + out << "●"; + break; + case white: + out << "○"; + break; + case null: + out << "╳"; + break; + default: + out << "╳"; + break; + } + ++pos; + }else{ + out << chr; + } + } +} + +choice board::select_choice(vector choices,const float& variation){ + + normal_distribution scatter(0,variation); + + for(choice& c:choices){ + c.rnd_val = c.val + scatter(engine); + } + + return *max_element( + choices.begin(),choices.end(), + [](const choice& c1,const choice& c2) -> bool{ + return c1.rnd_val < c2.rnd_val; + } + ); +} + +coordinate board::play(cmethod mthd,cbool color,cshort depth){ + + vector choices = get_choice(mthd,color,depth); + if(choices.empty()){ + return coordinate(-1,-1); + }else{ + choice best; + if(mthd == mthd_rnd){ + uniform_int_distribution scatter(0,choices.size() - 1); + best = choices[scatter(engine)]; + }else{ + float variation; + if(mthd & mthd_ptn){ + variation = 0.2; + }else{ + variation = 0.75; + } + best = select_choice(choices,variation); + } + flip(color,best.pos); + return coordinate(best.pos); + } +} + +float int2float(unsigned int n){ + return *(float*)&n; +} diff --git a/reversi.h b/cpp/reversi.h similarity index 75% rename from reversi.h rename to cpp/reversi.h index a4d65e7..fe36c56 100644 --- a/reversi.h +++ b/cpp/reversi.h @@ -18,12 +18,12 @@ #define REVERSI_H #include +#include #include #include #include #include #include -#include using namespace std; @@ -67,7 +67,6 @@ namespace std{ */ class board{ - friend struct hash; public: /** @fn board() @@ -78,29 +77,19 @@ class board{ To initial the object, please use the function initial() . */ board() = default; - board(cbrd_type _brd_black,cbrd_type _brd_white) + board(const board& brd) = default; + board(cull _brd_black,cull _brd_white) :brd_white(_brd_white),brd_black(_brd_black){} friend bool operator==(const board& b1,const board& b2){ - return (b1.brd_black == b2.brd_black) && (b1.brd_white == b2.brd_white); + return b1.brd_black == b2.brd_black && b1.brd_white == b2.brd_white; } friend bool operator!=(const board& b1,const board& b2){ - return (b1.brd_black != b2.brd_black) || (b1.brd_white != b2.brd_white); + return b1.brd_black != b2.brd_black || b1.brd_white != b2.brd_white; } static const pos_type size = 8; static const pos_type size2 = size * size; - static const pos_type pos_num = 4; - static const pos_type stage_num = 3; - static const short max_height = 20; - - static brd_type node_count; - - static bool flag_unicode; - - typedef pair interval; - - static calc_type table_param[stage_num][pos_num]; friend ostream& operator<<(ostream& out,const board& brd){ brd.print(out); @@ -113,12 +102,12 @@ class board{ */ void print(ostream& out = cout)const; - /** @fn board& assign(cbrd_type _brd_black,cbrd_type _brd_white) + /** @fn board& assign(cull _brd_black,cull _brd_white) * @brief Assign the board to some specific value. * @param _brd_black the value of the 64-bit board of black stones * @param _brd_black the value of the 64-bit board of white stones */ - void assign(cbrd_type _brd_black,cbrd_type _brd_white){ + void assign(cull _brd_black,cull _brd_white){ brd_black = _brd_black; brd_white = _brd_white; } @@ -130,10 +119,10 @@ class board{ return this->assign(0x0000000810000000,0x0000001008000000); } - cbrd_type bget(cbool color)const{ + cull bget(cbool color)const{ return *(&brd_white + color); } - brd_type& bget(cbool color){ + ull& bget(cbool color){ return *(&brd_white + color); } @@ -150,12 +139,12 @@ class board{ "bt %4, %3;" "cmovc %1, %0;" :"=&r"(result), "=&r"(temp) - :"r"(brd_black), "r"(brd_white), "r"(brd_type(pos)), + :"r"(brd_black), "r"(brd_white), "r"(ull(pos)), "g"(black), "g"(white) ); return result; #else - brd_type mask = brd_type(1) << pos; + ull mask = ull(1) << pos; if(mask & brd_black){ if(mask & brd_white){ return null; @@ -174,7 +163,7 @@ class board{ void set(cpos_type pos, cchessman chsm){ #ifdef USE_ASM - brd_type temp; + ull temp; asm volatile( "mov %0, %1;" "btr %2, %0;" @@ -182,7 +171,7 @@ class board{ "test %4, %3;" "cmovnz %1, %0;" :"+r"(brd_black), "=&r"(temp) - :"r"(brd_type(pos)), "r"(chsm), "g"(black) + :"r"(ull(pos)), "r"(chsm), "g"(black) ); asm volatile( "mov %0, %1;" @@ -191,10 +180,10 @@ class board{ "test %4, %3;" "cmovnz %1, %0;" :"+r"(brd_white), "=&r"(temp) - :"r"(brd_type(pos)), "r"(chsm), "g"(white) + :"r"(ull(pos)), "r"(chsm), "g"(white) ); #else - brd_type mask = brd_type(1) << pos; + ull mask = ull(1) << pos; if(chsm & white){ brd_white |= mask; }else{ @@ -208,39 +197,15 @@ class board{ #endif } - static brd_type extract(cbrd_type brd,cbrd_type mask){ - brd_type result; - - #ifdef USE_ASM_BMI - asm_pext(brd,mask,result); - #else - brd_type msk = mask; - result = 0; - for(brd_type i = 1;msk;i <<= 1){ - if(brd & msk & -msk){ - result |= i; - } - msk &= msk - 1; - } - #endif - + static ull extract(cull brd,cull mask){ + ull result; + fun_pext(brd,mask,result); return result; } - static brd_type deposit(cbrd_type brd,cbrd_type mask){ - brd_type result; - #ifdef USE_ASM_BMI - asm_pdep(brd,mask,result); - #else - brd_type msk = mask; - result = 0; - for(pos_type i = 1;msk;i <<= 1){ - if(brd & i){ - result |= msk & -msk; - } - msk &= msk - 1; - } - #endif + static ull deposit(cull brd,cull mask){ + ull result; + fun_pdep(brd,mask,result); return result; } @@ -248,21 +213,21 @@ class board{ swap(brd_black,brd_white); } - /** @fn static void mirror_h(brd_type& brd) + /** @fn static void mirror_h(ull& brd) * @brief It's a function used to mirror a 64-bit board horizontally. * @param brd the 64-bit board */ - static void mirror_h(brd_type& brd){ + static void mirror_h(ull& brd){ brd = (brd & 0xaaaaaaaaaaaaaaaa) >> 1 | (brd & 0x5555555555555555) << 1; brd = (brd & 0xcccccccccccccccc) >> 2 | (brd & 0x3333333333333333) << 2; brd = (brd & 0xf0f0f0f0f0f0f0f0) >> 4 | (brd & 0x0f0f0f0f0f0f0f0f) << 4; } - /** @fn static void mirror_v(brd_type& brd) + /** @fn static void mirror_v(ull& brd) * @brief It's a function used to mirror a 64-bit board vertically. * @param brd the 64-bit board */ - static void mirror_v(brd_type& brd){ + static void mirror_v(ull& brd){ #ifdef USE_ASM asm_bswap(brd); #else @@ -272,20 +237,20 @@ class board{ #endif } - /** @fn static void reflect(brd_type& brd) + /** @fn static void reflect(ull& brd) * @brief It's a function used to reflect a 64-bit board. * @param brd the 64-bit board */ - static void reflect(brd_type& brd){ + static void reflect(ull& brd){ mirror_h(brd); mirror_v(brd); } - /** @fn static void rotate_r(brd_type& brd) + /** @fn static void rotate_r(ull& brd) * @brief It's a function used to rotate a 64-bit board clockwise. * @param brd the 64-bit board */ - static void rotate_r(brd_type& brd){ + static void rotate_r(ull& brd){ brd = (brd & 0xf0f0f0f000000000) >> 4 | (brd & 0x0f0f0f0f00000000) >> 32 | (brd & 0x00000000f0f0f0f0) << 32 | (brd & 0x000000000f0f0f0f) << 4; brd = (brd & 0xcccc0000cccc0000) >> 2 | (brd & 0x3333000033330000) >> 16 @@ -294,11 +259,11 @@ class board{ | (brd & 0x00aa00aa00aa00aa) << 8 | (brd & 0x0055005500550055) << 1; } - /** @fn static void rotate_l(brd_type& brd) + /** @fn static void rotate_l(ull& brd) * @brief It's a function used to rotate a 64-bit board counter-clockwise. * @param brd the 64-bit board */ - static void rotate_l(brd_type& brd){ + static void rotate_l(ull& brd){ brd = (brd & 0xf0f0f0f000000000) >> 32 | (brd & 0x0f0f0f0f00000000) << 4 | (brd & 0x00000000f0f0f0f0) >> 4 | (brd & 0x000000000f0f0f0f) << 32; brd = (brd & 0xcccc0000cccc0000) >> 16 | (brd & 0x3333000033330000) << 2 @@ -307,13 +272,13 @@ class board{ | (brd & 0x00aa00aa00aa00aa) >> 1 | (brd & 0x0055005500550055) << 8; } - /** @fn static void count(brd_type& brd) + /** @fn static void count(ull& brd) * @brief It's a function used to count the number of bit * which are set in a 64-bit board. * @param brd the 64-bit board */ - static pos_type count(cbrd_type brd){ - brd_type result; + static pos_type count(cull brd){ + ull result; #ifdef USE_ASM asm_popcnt(brd,result); @@ -328,12 +293,12 @@ class board{ return result; } - /** @fn static brd_type get_edge_stable(cbrd_type brd) + /** @fn static ull get_edge_stable(cull brd) * @brief It's a function used to estimate which stones are stable. * @param brd the 64-bit board */ - static brd_type get_edge_stable(cbrd_type brd){ - brd_type brd_ul,brd_ur,brd_dl,brd_dr; + static ull get_edge_stable(cull brd){ + ull brd_ul,brd_ur,brd_dl,brd_dr; brd_ul = brd; brd_ul &= (brd_ul >> 1) | 0x8080808080808080; @@ -362,12 +327,12 @@ class board{ return brd_ul | brd_ur | brd_dl | brd_dr; } - /** @fn static brd_type get_edge_stable(cbrd_type brd) + /** @fn static ull get_edge_stable(cull brd) * @brief It's a function used to estimate which stones are stable. * @param brd the 64-bit board */ - static brd_type get_stable(cbrd_type brd){ - brd_type brd_l,brd_r,brd_u,brd_d,brd_ul,brd_ur,brd_dl,brd_dr; + static ull get_stable(cull brd){ + ull brd_l,brd_r,brd_u,brd_d,brd_ul,brd_ur,brd_dl,brd_dr; brd_l = brd; brd_l &= (brd_l >> 1) | 0x8080808080808080; @@ -413,12 +378,12 @@ class board{ & (brd_ul | brd_dr) & (brd_ur | brd_dl); } - /** @fn static brd_type get_front(cbrd_type brd) + /** @fn static ull get_front(cull brd) * @brief It's a function used to calculate the frontier. * @param brd the 64-bit board */ - static brd_type get_front(cbrd_type brd){ - brd_type brd_reverse, brd_front; + static ull get_front(cull brd){ + ull brd_reverse, brd_front; brd_reverse = ~brd; brd_front = 0; @@ -471,20 +436,31 @@ class board{ return count(brd_black | brd_white); } - /** @fn brd_type get_move(cbool color)const + ull get_key(cbool color)const{ + ull result = (brd_black * 0xe2abbb5e6688fdcf) ^ (brd_white * 0x34df417f070da53d); + fun_rol(result, 20); + result += color; + return result; + } + + static ull get_count(); + static void clear_count(); + static void clear_hash(); + + /** @fn ull get_move(cbool color)const * @brief Calculate possible moves. * @param color Whether it is black's turn. */ - brd_type get_move(cbool color)const{ + ull get_move(cbool color)const{ // This part of code is brought from Zebra. // I rewrite it in 64-bit style. - const brd_type& brd_blue = bget(color); - const brd_type& brd_green = bget(!color); - brd_type moves; - brd_type brd_green_inner; - brd_type brd_flip; - brd_type brd_green_adj; + const ull& brd_blue = bget(color); + const ull& brd_green = bget(!color); + ull moves; + ull brd_green_inner; + ull brd_flip; + ull brd_green_adj; brd_green_inner = brd_green & 0x7E7E7E7E7E7E7E7Eu; @@ -577,26 +553,82 @@ class board{ config_search(); } - static void clear_search_info(); + pair process_method(cmethod mthd, cshort depth){ + pair result = {mthd, depth}; + short total = this->sum(); + + if(result.first == mthd_rnd){ + return result; + } + + if(result.second == -1){ + if(total <= 7){ + result.second = 10; + }else if(total <= 10){ + result.second = 9; + }else if(total <= size2 - 22){ + result.second = 8; + }else if(total <= size2 - 15){ + result.second = 9; + }else{ + result.second = 20; + } + }else if(result.second == -2){ + if(total <= 7){ + result.second = 10; + }else if(total <= 10){ + result.second = 10; + }else if(total <= size2 - 24){ + result.second = 9; + }else if(total <= size2 - 16){ + result.second = 10; + }else{ + result.second = 20; + } + }else if(result.second <= -3){ + if(total <= 7){ + result.second = 11; + }else if(total <= 10){ + result.second = 11; + }else if(total <= size2 - 22){ + result.second = 10; + }else if(total <= size2 - 16){ + result.second = 11; + }else{ + result.second = 20; + } + } + if(result.second >= size2 - total){ + result.first = method(mthd | mthd_end); + result.second = size2 - total; + } + return result; + } void flip(cbool color,cpos_type pos); - calc_type score_end(cbool color)const{ - calc_type num_diff = count(color) - count(!color); + val_type score_end(cbool color)const{ + val_type num_diff = count(color) - count(!color); + if(num_diff > 0){ - return num_diff + mark_max; + return num_diff + 2; }else if(num_diff < 0){ - return num_diff - mark_max; + return num_diff - 2; }else{ return 0; } } - calc_type score(cbool color)const{ - brd_type brd_blue = bget(color); - brd_type brd_green = bget(!color); - brd_type brd_mix = brd_blue | brd_green; - brd_type brd_temp; + val_type score(cbool color)const{ + ull brd_blue = bget(color); + ull brd_green = bget(!color); + ull brd_mix = brd_blue | brd_green; + ull brd_temp; + const val_type table_param[3][4] = { + {12,0.5,-6,-0.2}, + {10,0.5,-5,0.2}, + {3,1,0,0} + }; short stage; short total = count(brd_mix); @@ -608,7 +640,7 @@ class board{ stage = 2; } - calc_type result = 0; + val_type result = 0; result += count_move(color) - count_move(!color); brd_temp = get_stable(brd_mix); result += count(brd_blue & brd_temp) - count(brd_green & brd_temp); @@ -628,34 +660,34 @@ class board{ } template - calc_type search( + val_type search( cbool color,cshort height, - calc_type alpha = _inf,calc_type beta = inf,cbool flag_pass = false + val_type alpha = _inf,val_type beta = inf,cbool flag_pass = false )const; - calc_type search( + val_type search( cmethod mthd,cbool color,cshort height, - ccalc_type alpha = _inf,ccalc_type beta = inf + cval_type alpha = _inf,cval_type beta = inf )const; - calc_type search_end_two( + val_type search_end_two( cbool color,cpos_type pos1,cpos_type pos2, - calc_type alpha,calc_type beta,cbool flag_pass + val_type alpha,val_type beta,cbool flag_pass )const; - calc_type search_end_three( + val_type search_end_three( cbool color,cpos_type pos1,cpos_type pos2,cpos_type pos3, - calc_type alpha,calc_type beta,cbool flag_pass + val_type alpha,val_type beta,cbool flag_pass )const; - calc_type search_end_four( + val_type search_end_four( cbool color,cpos_type pos1,cpos_type pos2,cpos_type pos3,cpos_type pos4, - calc_type alpha,calc_type beta,cbool flag_pass + val_type alpha,val_type beta,cbool flag_pass )const; template - calc_type search_end_five( - cbool color,calc_type alpha,calc_type beta,cbool flag_pass + val_type search_end_five( + cbool color,val_type alpha,val_type beta,cbool flag_pass )const; vector get_choice(cmethod mthd,cbool color,cshort depth)const; static choice select_choice(vector choices,const float& variation = 0.75); - coordinate play(cmethod mthd,cbool color,short depth = -1); + coordinate play(cmethod mthd,cbool color,cshort depth = -1); sts_type get_status(cbool color){ const sts_type table_status[32] = { @@ -684,30 +716,19 @@ class board{ float score_ptn(cbool color,const pattern& ptn)const; void adjust_ptn(cbool color,pattern& ptn,cfloat value)const; + #ifdef DEBUG_SEARCH + static void enable_log(); + static void disable_log(); + static void clear_log(); + static void save_log(const string& filename); + #endif //DEBUG_SEARCH + protected: - brd_type brd_white,brd_black; + ull brd_white,brd_black; static void config_flip(); static void config_search(); - - #ifdef USE_FLOAT - static const calc_type mark_max; - #else - static const calc_type mark_max = 2; - #endif -}; - -template <> -struct std::hash : public unary_function{ - size_t operator()(const board& brd) const{ - return ( - size_t(brd.brd_black) - + size_t(brd.brd_black >> 32) * 1867970917 - + size_t(brd.brd_white) * 1009562269 - + size_t(brd.brd_white >> 32) * 739351663 - ); - } }; struct choice{ @@ -717,4 +738,6 @@ struct choice{ pos_type pos; }; +float int2float(unsigned int n); + #endif // REVERSI_H diff --git a/search.cc b/cpp/search.cc similarity index 56% rename from search.cc rename to cpp/search.cc index 1edc29f..2715f52 100644 --- a/search.cc +++ b/cpp/search.cc @@ -8,14 +8,11 @@ #include "reversi.h" #include "search.h" #include "pattern.h" +#include "hash.h" -#ifdef USE_ASM - #define trail_zero_count(brd,result) \ - asm_tzcnt(brd,result) -#else - #define trail_zero_count(brd,result) \ - result = count(~brd & (brd - 1)) -#endif +#ifdef DEBUG_SEARCH + #include "log.h" +#endif //DEBUG_SEARCH const short depth_kill = 2; const short depth_pvs = 2; @@ -23,21 +20,43 @@ const short depth_hash = 3; const short depth_mtdf = 4; const short depth_mpc = 3; -calc_type table_val[board::size2 + 1][board::size2]; -trans_type table_trans[2]; - -const calc_type table_val_init[board::size2] = { - 0.0010,0.0003,0.0007,0.0008,0.0008,0.0007,0.0003,0.0010, - 0.0003,0.0002,0.0004,0.0005,0.0005,0.0004,0.0002,0.0003, - 0.0007,0.0004,0.0009,0.0006,0.0006,0.0009,0.0004,0.0007, - 0.0008,0.0005,0.0006,0.0001,0.0001,0.0006,0.0005,0.0008, - 0.0008,0.0005,0.0006,0.0001,0.0001,0.0006,0.0005,0.0008, - 0.0007,0.0004,0.0009,0.0006,0.0006,0.0009,0.0004,0.0007, - 0.0003,0.0002,0.0004,0.0005,0.0005,0.0004,0.0002,0.0003, - 0.0010,0.0003,0.0007,0.0008,0.0008,0.0007,0.0003,0.0010 -}; +val_type table_val[board::size2 + 1][board::size2]; +ull node_count; +bucket bkt; +double table_predict[65][32][32][4]; + +ull board::get_count(){ + return node_count; +} +void board::clear_count(){ + node_count = 0; +} + +void board::clear_hash(){ + bkt.clear(); +} + +#ifdef DEBUG_SEARCH + log_record search_log; + + void board::enable_log(){ + search_log.enable(); + } + void board::disable_log(){ + search_log.disable(); + } + void board::clear_log(){ + search_log.clear(); + } + void board::save_log(const string& filename){ + search_log.save(filename); + } -const brd_type mask_adj[board::size2] = { + short height = 0; + +#endif //DEBUG_SEARCH + +const ull mask_adj[board::size2] = { 0x0000000000000302, 0x0000000000000705, 0x0000000000000e0a, @@ -115,10 +134,10 @@ struct mtdf_info{ mtdf_info():num(1),bias(0),sigma(1){} int num; - calc_type bias; - calc_type sigma; + val_type bias; + val_type sigma; - void adjust(ccalc_type diff){ + void adjust(cval_type diff){ bias *= num; sigma *= num; bias += diff; @@ -142,34 +161,11 @@ short table_mtdf_depth[board::size2] = { 6,5,6,5,6,5,6,5, }; -short table_mpc_depth[board::size2] = { - 0,0,0,0,0,1,2,3, - 4,4,4,5,5,5,5,5, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6 -}; - -calc_type table_mpc_threshold[board::size2] = { - 2.50,2.57,2.65,2.73,2.81,2.90,2.99,3.08, - 3.18,3.28,3.39,3.50,3.61,3.73,3.85,3.98, - 4.11,4.24,4.38,4.52,4.66,4.81,4.96,5.12, - 5.27,5.44,5.60,5.78,5.95,6.13,6.31,6.50, - 6.69,6.88,7.08,7.28,7.48,7.69,7.90,8.12, - 8.34,8.56,8.79,9.02,9.26,9.50,9.74,9.99, - 10.24,10.49,10.75,11.01,11.28,11.55,11.82,12.10, - 12.38,12.66,12.95,13.24,13.54,13.84,14.14,14.45 -}; - -void board::config_search(){} - -void board::clear_search_info(){ - node_count = 0; - table_trans[0].clear(); - table_trans[1].clear(); +void board::config_search(){ + ifstream in("data/reversi_table_predict.dat", ios::binary | ios::in); + in.seekg(0xa2); + in.read((char*)table_predict, sizeof(table_predict)); + in.close(); } #ifdef __GNUC__ @@ -177,9 +173,9 @@ void board::clear_search_info(){ #pragma GCC diagnostic ignored "-Wswitch" #endif -calc_type board::search( +val_type board::search( cmethod mthd,cbool color,cshort depth, - ccalc_type alpha,ccalc_type beta + cval_type alpha,cval_type beta )const{ if(mthd & mthd_ids){ @@ -197,30 +193,26 @@ calc_type board::search( method mthd_presearch = method(mthd_de_mtdf & ~mthd_end & ~mthd_trans); short depth_presearch = table_mtdf_depth[depth]; - calc_type gamma = this->search(mthd_presearch,color,depth_presearch); + val_type gamma = this->search(mthd_presearch,color,depth_presearch); mtdf_info& info = table_mtdf_info[this->sum()][depth][depth_presearch]; - calc_type window_width = sqrt(info.sigma) * 2; - calc_type window_alpha = gamma + info.bias - window_width / 2; - calc_type window_beta = gamma + info.bias + window_width / 2; + val_type window_width = sqrt(info.sigma) * 2; + val_type window_alpha = gamma + info.bias - window_width / 2; + val_type window_beta = gamma + info.bias + window_width / 2; - calc_type result = this->search(mthd_de_mtdf,color,depth, window_alpha, window_beta); + val_type result = this->search(mthd_de_mtdf,color,depth, window_alpha, window_beta); if(result <= window_alpha && result > alpha){ do{ - //window_width *= 2; window_beta = result; window_alpha = window_beta - window_width; - //window_alpha = max(window_beta - window_width,alpha); result = this->search(mthd_de_mtdf,color,depth, window_alpha, window_beta); }while(result <= window_alpha && result > alpha); }else if(result >= window_beta && result < beta){ do{ - //window_width *= 2; window_alpha = result; window_beta = window_alpha + window_width; - //window_beta = min(window_alpha + window_width,beta); result = this->search(mthd_de_mtdf,color,depth, window_alpha, window_beta); }while(result >= window_beta && result < beta); } @@ -269,7 +261,7 @@ calc_type board::search( struct brd_val{ pos_type pos; - calc_type val; + val_type val; friend bool operator<(const brd_val& b1,const brd_val& b2){ return b1.val < b2.val; } @@ -282,10 +274,12 @@ typedef const brd_val& cbrd_val; #endif template -calc_type board::search(cbool color,cshort depth,calc_type alpha,calc_type beta,cbool flag_pass)const{ +val_type board::search(cbool color,cshort depth,val_type alpha,val_type beta,cbool flag_pass)const{ #ifdef DEBUG_SEARCH - auto fun = [&]()->calc_type{ + val_type _alpha = alpha; + val_type _beta = beta; + auto fun = [&]()->val_type{ #endif if(mthd == mthd_rnd){ @@ -307,82 +301,111 @@ calc_type board::search(cbool color,cshort depth,calc_type alpha,calc_type beta, return this->score(color); } + bool flag_kill = (mthd & mthd_kill) && depth >= depth_kill; + bool flag_pvs = (mthd & mthd_pvs) && depth >= depth_pvs; bool flag_hash = (mthd & mthd_trans) && depth >= depth_hash; + bool flag_mpc = (mthd & mthd_mpc) && depth >= depth_mpc; - calc_type alpha_save; + ull key = get_key(color); + slot* slt; + ull pos; + ull best_pos = -1; + val_type alpha_save = alpha; + val_type* ptr_val = table_val[this->sum()]; if(flag_hash){ - trans_type::iterator trans_ptr = table_trans[color].find(*this); - if(trans_ptr != table_trans[color].end()){ - auto& trans_interval = trans_ptr->second; - if(trans_interval.first >= beta){ - return trans_interval.first; - } - if(trans_interval.second <= alpha){ - return trans_interval.second; + slt = &bkt.probe(key); + if(*this == slt->brd){ + if(depth == slt->depth){ + if(alpha >= slt->beta){ + return alpha; + } + if(beta <= slt->alpha){ + return beta; + } + alpha = max(alpha, slt->alpha); + beta = min(beta, slt->beta); + if(alpha == beta){ + return alpha; + } + #ifdef DEBUG_SEARCH + if(alpha >= beta){ + throw 1; + }; + #else + assert(alpha < beta); + #endif } - if(trans_interval.first > alpha){ - alpha = trans_interval.first; + if(flag_kill){ + ptr_val[slt->pos] += 10; } - if(trans_interval.second < beta){ - beta = trans_interval.second; + } + } + + const method mthd_presearch = method(mthd & ~mthd_pvs & ~mthd_mtdf & ~mthd_end); + short cnt = sum(); + val_type temp; + + if(flag_mpc && (table_predict[cnt][0][depth][0] >= 40)){ + const val_type mpc_alpha = -0.5; + const val_type mpc_beta = 2.0; + short depth_start = depth & 1; + + temp = this->template search(color, depth_start); + val_type bias = table_predict[cnt][depth_start][depth][1]; + val_type sigma = table_predict[cnt][depth_start][depth][2]; + + if(temp + bias + sigma * mpc_beta < alpha){ + return temp + bias; + }else if(temp + bias - sigma * mpc_beta > beta){ + return temp + bias; + } + if(temp + bias + sigma * mpc_alpha < alpha){ + val_type bound; + for(int i = depth_start + 2; i < min(depth, short(10)); i += 2){ + bias = table_predict[cnt][i][depth][1]; + sigma = table_predict[cnt][i][depth][2]; + bound = alpha - sigma * mpc_beta - bias; + temp = this->template search(color, i, bound - 0.001, bound); + if(temp < bound){ + return temp + bias; + } } - if(alpha == beta){ - return alpha; + } + if(temp + bias - sigma * mpc_alpha > beta){ + val_type bound; + for(int i = depth_start + 2; i < min(depth, short(10)); i += 2){ + bias = table_predict[cnt][i][depth][1]; + sigma = table_predict[cnt][i][depth][2]; + bound = beta + sigma * mpc_beta - bias; + temp = this->template search(color, i, bound, bound + 0.001); + if(temp > bound){ + return temp + bias; + } } - assert(alpha <= beta); - }else{ - table_trans[color][*this] = interval(_inf,inf); } - alpha_save = alpha; } - bool flag_kill = (mthd & mthd_kill) && depth >= depth_kill; - bool flag_pvs = (mthd & mthd_pvs) && depth >= depth_pvs; - bool flag_mpc = (mthd & mthd_mpc) && depth >= depth_mpc; - brd_val vec[32]; brd_val* ptr = vec; board brd; - calc_type temp, result = _inf; - calc_type* ptr_val = table_val[this->sum()]; + val_type result = _inf; const method mthd_de_pvs = method(mthd & ~mthd_pvs); - brd_type brd_move = this->get_move(color); - brd_type pos; + ull brd_move = this->get_move(color); - trail_zero_count(brd_move,pos); + fun_tzcnt(brd_move, pos); while(brd_move){ ptr->pos = pos; - if(flag_mpc){ - const method mthd_presearch = method(mthd & ~mthd_end & ~mthd_trans); - board brd = *this; - brd.flip(color,pos); - ptr->val = - brd.search(!color,table_mpc_depth[depth]); - }else if(flag_kill){ + if(flag_kill){ ptr->val = ptr_val[pos]; } ++ptr; brd_move &= brd_move - 1; - trail_zero_count(brd_move,pos); + fun_tzcnt(brd_move, pos); } if(ptr != vec){ - if(flag_mpc){ - calc_type best = max_element( - vec,ptr, - [](cbrd_val b1,cbrd_val b2) -> bool{ - return b1.val < b2.val; - } - )->val; - calc_type mpc_threshold = table_mpc_threshold[this->sum()]; - ptr = remove_if(vec,ptr, - [&mpc_threshold,&best](cbrd_val b) -> bool{ - return b.val < best - mpc_threshold; - } - ); - } - if(flag_kill){ make_heap(vec,ptr, [](cbrd_val b1,cbrd_val b2) -> bool{ @@ -411,19 +434,24 @@ calc_type board::search(cbool color,cshort depth,calc_type alpha,calc_type beta, } if(temp >= beta){ if(flag_hash){ - table_trans[color][*this].first = temp; + slt->save(slot{*this, temp, inf, depth, (short)p->pos}); } return temp; } - result = max(result,temp); + if(temp > result){ + result = temp; + if(flag_hash){ + best_pos = pos; + } + } alpha = max(alpha,result); } if(flag_hash){ if(result > alpha_save){ - table_trans[color][*this] = {result,result}; + slt->save(slot{*this, result, result, depth, short(best_pos)}); }else{ - table_trans[color][*this].second = result; + slt->save(slot{*this, _inf, result, depth, short(best_pos)}); } } @@ -431,13 +459,13 @@ calc_type board::search(cbool color,cshort depth,calc_type alpha,calc_type beta, }else if(!flag_pass){ - return - this->template search(!color,depth,-beta,-alpha,true); + return - this->template search(!color, depth, -beta, -alpha, true); }else{ result = score_end(color); if(flag_hash){ - table_trans[color][*this] = {result,result}; + slt->save(slot{*this, result, result, depth, -1}); } return result; @@ -447,15 +475,20 @@ calc_type board::search(cbool color,cshort depth,calc_type alpha,calc_type beta, #ifdef DEBUG_SEARCH }; - out << "
\n"; - this->print(out); - calc_type result = fun(); - out << "result = " << result << "\n" - << "
\n"; + val_type result; + try{ + ++height; + result = fun(); + --height; + }catch(int n){ + --height; + search_log.insert(node{*this, color, height, depth, _alpha, _beta, result}); + if(height == 0){ + save_log("except.dat"); + } + throw n; + } + search_log.insert(node{*this, color, height, depth, _alpha, _beta, result}); return result; #endif } @@ -464,21 +497,23 @@ calc_type board::search(cbool color,cshort depth,calc_type alpha,calc_type beta, #pragma GCC diagnostic pop #endif -calc_type board::search_end_two( - cbool color,cpos_type pos1,cpos_type pos2,calc_type alpha,calc_type beta,cbool flag_pass +val_type board::search_end_two( + cbool color,cpos_type pos1,cpos_type pos2,val_type alpha,val_type beta,cbool flag_pass )const{ #ifdef DEBUG_SEARCH - auto fun = [&]()->calc_type{ + val_type _alpha = alpha; + val_type _beta = beta; + auto fun = [&]()->val_type{ #endif ++node_count; board brd; - brd_type brd_blue = bget(color); - brd_type brd_green = bget(!color); - brd_type brd_save; - calc_type result = _inf,temp; + ull brd_blue = bget(color); + ull brd_green = bget(!color); + ull brd_save; + val_type result = _inf,temp; if(brd_green | mask_adj[pos1]){ brd = *this; @@ -532,35 +567,30 @@ calc_type board::search_end_two( #ifdef DEBUG_SEARCH }; - out << "
\n"; - this->print(out); - calc_type result = fun(); - out << "result = " << result << "\n" - << "
\n"; + ++height; + val_type result = fun(); + --height; + search_log.insert(node{*this, color, height, 2, _alpha, _beta, result}); return result; #endif } -calc_type board::search_end_three( - cbool color,cpos_type pos1,cpos_type pos2,cpos_type pos3,calc_type alpha,calc_type beta,cbool flag_pass +val_type board::search_end_three( + cbool color,cpos_type pos1,cpos_type pos2,cpos_type pos3,val_type alpha,val_type beta,cbool flag_pass )const{ #ifdef DEBUG_SEARCH - auto fun = [&]()->calc_type{ + val_type _alpha = alpha; + val_type _beta = beta; + auto fun = [&]()->val_type{ #endif ++node_count; board brd; - brd_type brd_green = bget(!color); - calc_type result = _inf,temp; + ull brd_green = bget(!color); + val_type result = _inf,temp; if(brd_green | mask_adj[pos1]){ brd = *this; @@ -613,36 +643,30 @@ calc_type board::search_end_three( #ifdef DEBUG_SEARCH }; - out << "
\n"; - this->print(out); - calc_type result = fun(); - out << "result = " << result << "\n" - << "
\n"; + ++height; + val_type result = fun(); + --height; + search_log.insert(node{*this, color, height, 3, _alpha, _beta, result}); return result; #endif } -calc_type board::search_end_four( - cbool color,cpos_type pos1,cpos_type pos2,cpos_type pos3,cpos_type pos4,calc_type alpha,calc_type beta,cbool flag_pass +val_type board::search_end_four( + cbool color,cpos_type pos1,cpos_type pos2,cpos_type pos3,cpos_type pos4,val_type alpha,val_type beta,cbool flag_pass )const{ #ifdef DEBUG_SEARCH - auto fun = [&]()->calc_type{ + val_type _alpha = alpha; + val_type _beta = beta; + auto fun = [&]()->val_type{ #endif ++node_count; board brd; - brd_type brd_green = bget(!color); - calc_type result = _inf,temp; + ull brd_green = bget(!color); + val_type result = _inf,temp; if(brd_green | mask_adj[pos1]){ brd = *this; @@ -708,48 +732,41 @@ calc_type board::search_end_four( #ifdef DEBUG_SEARCH }; - out << "
\n"; - this->print(out); - calc_type result = fun(); - out << "result = " << result << "\n" - << "
\n"; + ++height; + val_type result = fun(); + --height; + search_log.insert(node{*this, color, height, 4, _alpha, _beta, result}); return result; #endif } template -calc_type board::search_end_five( - cbool color,calc_type alpha,calc_type beta,cbool flag_pass +val_type board::search_end_five( + cbool color,val_type alpha,val_type beta,cbool flag_pass )const{ #ifdef DEBUG_SEARCH - auto fun = [&]()->calc_type{ + val_type _alpha = alpha; + val_type _beta = beta; + auto fun = [&]()->val_type{ #endif const bool flag_kill = (mthd & mthd_kill); // bool flag_pvs = (mthd & mthd_pvs) && depth >= depth_pvs; // bool flag_hash = (mthd & mthd_trans) && depth >= depth_hash; - brd_type brd_blank = ~(brd_black | brd_white); + ull brd_blank = ~(brd_black | brd_white); brd_val vec[32]; brd_val* ptr = vec; board brd; - calc_type result = _inf,temp; - calc_type* ptr_val = table_val[this->sum()]; - brd_type brd_green = bget(false); - brd_type pos; + val_type result = _inf,temp; + val_type* ptr_val = table_val[this->sum()]; + ull brd_green = bget(false); + ull pos; - trail_zero_count(brd_blank,pos); + fun_tzcnt(brd_blank, pos); while(brd_blank){ ptr->pos = pos; if(mthd & mthd_kill){ @@ -757,7 +774,7 @@ calc_type board::search_end_five( } ++ptr; brd_blank &= brd_blank - 1; - trail_zero_count(brd_blank,pos); + fun_tzcnt(brd_blank, pos); } sort(vec,ptr, @@ -801,59 +818,46 @@ calc_type board::search_end_five( #ifdef DEBUG_SEARCH }; - out << "
\n"; - this->print(out); - calc_type result = fun(); - out << "result = " << result << "\n" - << "
\n"; + ++height; + val_type result = fun(); + --height; + search_log.insert(node{*this, color, height, 5, _alpha, _beta, result}); return result; #endif } vector board::get_choice( - cmethod mthd,cbool color,cshort height + cmethod mthd,cbool color,cshort depth )const{ + #ifdef DEBUG_SEARCH + auto fun = [&]()->vector{ + #endif + vector choices; - calc_type result; + val_type result,best; choice temp; - calc_type alpha = _inf; - calc_type threshold = (mthd & mthd_ptn) ? 3 : 5; - calc_type* ptr_val = table_val[this->sum()]; - - clear_search_info(); - -// if(mthd & mthd_kill){ -// for(int i = this->sum();i != size2;++i){ -// for(int j = 0;j != size2;++j){ -// if(table_val[i][j] == 0){ -// table_val[i][j] = table_val_init[j]; -// } -// } -// } -// } + val_type alpha = _inf, beta = inf; + val_type threshold = (mthd & mthd_ptn) ? 3 : 5; + val_type* ptr_val = table_val[this->sum()]; choices.reserve(30); - brd_type brd_move = this->get_move(color); - brd_type pos; + ull brd_move = this->get_move(color); + ull pos; - trail_zero_count(brd_move,pos); + fun_tzcnt(brd_move, pos); while(brd_move){ temp.brd = *this; temp.pos = pos; - temp.brd.flip(color,pos); + temp.brd.flip(color, pos); if(mthd & mthd_kill){ temp.rnd_val = ptr_val[pos]; } choices.push_back(temp); brd_move &= brd_move - 1; - trail_zero_count(brd_move,pos); + fun_tzcnt(brd_move, pos); } if(mthd == mthd_rnd){ @@ -868,16 +872,106 @@ vector board::get_choice( ); } + + /* + if(mthd & mthd_mtdf){ + method mthd_de_mtdf = method(mthd & ~mthd_mtdf); + + if(depth >= depth_mtdf){ + + method mthd_presearch = method(mthd_de_mtdf & ~mthd_end); + short depth_presearch = table_mtdf_depth[depth]; + + val_type gamma = this->search(mthd_presearch,color,depth_presearch); + + mtdf_info& info = table_mtdf_info[this->sum()][depth][depth_presearch]; + + val_type window_width = sqrt(info.sigma) * 2; + val_type window_alpha = gamma + info.bias - window_width / 2; + val_type window_beta = gamma + info.bias + window_width / 2; + + clear_search_info(); + + best = _inf; + for(choice& c:choices){ + result = - c.brd.search(mthd_de_mtdf,!color,depth - 1,-window_beta,-window_alpha); + c.val = result; + best = max(best,result); + } + + if(best <= window_alpha && best > alpha){ + do{ + //window_width *= 2; + window_beta = best; + window_alpha = window_beta - window_width; + //window_alpha = max(window_beta - window_width,alpha); + best = _inf; + for(choice& c:choices){ + result = - c.brd.search(mthd_de_mtdf,!color,depth - 1,-window_beta,-window_alpha); + c.val = result; + best = max(best,result); + } + }while(best <= window_alpha && best > alpha); + }else if(best >= window_beta && best < beta){ + do{ + //window_width *= 2; + window_alpha = best; + window_beta = window_alpha + window_width; + //window_beta = min(window_alpha + window_width,beta); + best = _inf; + for(choice& c:choices){ + result = - c.brd.search(mthd_de_mtdf,!color,depth - 1,-window_beta,-window_alpha); + c.val = result; + best = max(best,result); + } + }while(best >= window_beta && best < beta); + } + + if(best > alpha && best < beta){ + info.adjust(best - gamma); + } + + }else{ + best = _inf; + for(choice& c:choices){ + result = - c.brd.search(mthd_de_mtdf, !color, depth - 1, -beta, -alpha); + if(mthd & mthd_kill){ + ptr_val[c.pos] = result; + } + best = max(best,result); + alpha = best - threshold; + c.val = result; + } + } + return choices; + } + */ + + best = _inf; for(choice& c:choices){ - result = - c.brd.search(mthd,!color,height,_inf,-alpha); + result = - c.brd.search(mthd, !color, depth - 1, -beta, -alpha); if(mthd & mthd_kill){ ptr_val[c.pos] = result; } - if(result - threshold > alpha){ - alpha = result - threshold; - } + best = max(best,result); + alpha = best - threshold; c.val = result; } return choices; + + #ifdef DEBUG_SEARCH + }; + ++height; + vector result = fun(); + --height; + val_type best = max_element( + result.begin(), result.end(), + [](const choice& c1,const choice& c2) -> bool{ + return c1.rnd_val < c2.rnd_val; + } + )->val; + search_log.insert(node{*this, color, height, depth, _inf, inf, best}); + return result; + #endif } diff --git a/cpp/tree.h b/cpp/tree.h new file mode 100644 index 0000000..a81000c --- /dev/null +++ b/cpp/tree.h @@ -0,0 +1,45 @@ +#include + +#include "board.h" + +struct node{ + node* parent; + node* sibling; + node* child; + board brd; + bool color; + short pos; + short count_leaf; + float value; + int win_white, win_black; + + node(node* const& _parent, cboard _brd, cbool _color, cshort _pos, cfloat value) + : parent(parent), sibling(NULL), child(NULL), brd(_board), color(_color), + pos(pos), count_leaf(0), value(_value), win_black(0), win_white(0){} + + void destroy(){ + if(this){ + sibling->destroy(); + child->destroy(); + delete this; + } + } + + int& get_win(cbool color){ + return *(&win_white + color); + } + cint get_win(cbool color)const{ + return *(&win_white + color); + } + + void expand(cbool color){ + ull brd_move = brd.get_move(color); + while(brd_move){ + + brd_move &= brd_move - 1; + } + } + + void descend(){ + } +}; diff --git a/type.h b/cpp/type.h similarity index 55% rename from type.h rename to cpp/type.h index c77db77..837e2dd 100644 --- a/type.h +++ b/cpp/type.h @@ -10,64 +10,49 @@ using namespace std; //#define USE_REF -#define USE_FLOAT // check whether the complier support 64-bit AT&T inline assembly #if defined(__GNUC__) || defined(__clang__) #if defined(__x86_64__) || defined(__ppc64__) #define USE_ASM - #define USE_ASM_BMI + //#define USE_ASM_BMI2 #endif #endif #ifndef USE_ASM - #undef USE_ASM_BMI + #undef USE_ASM_BMI2 #endif +#ifdef _BOTZONE_ONLINE + #define USE_ASM + #define USE_ASM_BMI2 +#endif //_BOTZONE_ONLINE //#define DEBUG_SEARCH -#ifdef USE_REF - typedef const bool& cbool; - typedef const short& cshort; - typedef const int& cint; - typedef const float& cfloat; -#else - typedef bool cbool; - typedef short cshort; - typedef int cint; - typedef float cfloat; -#endif //USE_REF +typedef const bool& cbool; +typedef const short& cshort; +typedef const int& cint; +typedef const float& cfloat; +typedef long long ll; +typedef const ll& cll; +typedef unsigned long long ull; +typedef const ull& cull; -typedef unsigned long long brd_type; typedef unsigned char line_type; +typedef const line_type& cline_type; typedef short pos_type; +typedef const pos_type& cpos_type; -#ifdef USE_FLOAT - typedef float calc_type; -#else - typedef short calc_type; -#endif - -#ifdef USE_REF - typedef const brd_type& cbrd_type; - typedef const line_type& cline_type; - typedef const pos_type& cpos_type; - typedef const calc_type& ccalc_type; -#else - typedef brd_type cbrd_type; - typedef line_type cline_type; - typedef pos_type cpos_type; - typedef calc_type ccalc_type; -#endif //USE_REF - -enum chessman{blank,white,black,null}; +typedef float val_type; +typedef const val_type& cval_type; +enum chessman{blank, white, black, null}; #ifdef USE_REF typedef const chessman& cchessman; #else typedef chessman cchessman; #endif //USE_REF -const calc_type inf = numeric_limits::max(); -const calc_type _inf = - inf; +const val_type inf = numeric_limits::max(); +const val_type _inf = - inf; enum method{ @@ -109,26 +94,23 @@ enum sts_type{ #include extern default_random_engine engine; -#ifdef DEBUG_SEARCH - #include - extern ofstream out; -#endif - class board; +typedef const board& cboard; struct choice; +typedef const choice& cchoice; class pattern; +typedef const pattern& cpattern; class group; +typedef const group& cgroup; +enum player_type{ + ply_human,ply_ai,ply_other +}; #ifdef USE_REF - typedef const board& cboard; - typedef const choice& cchoice; - typedef const pattern& cpattern; - typedef const group& cgroup; + typedef const player_type& cplayer_type; #else - typedef board cboard; - typedef choice cchoice; - typedef pattern cpattern; - typedef group cgroup; + typedef player_type cplayer_type; #endif //USE_REF -#endif //TYPE_H \ No newline at end of file + +#endif //TYPE_H diff --git a/cpptcl.cc b/cpptcl.cc deleted file mode 100644 index 48f5c3a..0000000 --- a/cpptcl.cc +++ /dev/null @@ -1,1082 +0,0 @@ -// -// Copyright (C) 2004-2006, Maciej Sobczak -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// - -#include "cpptcl.h" -#include -#include -#include - - -using namespace Tcl; -using namespace Tcl::details; -using namespace std; -using namespace std; - -result::result(Tcl_Interp *interp) : interp_(interp) {} - -result::operator bool() const -{ - Tcl_Obj *obj = Tcl_GetObjResult(interp_); - - int val, cc; - cc = Tcl_GetBooleanFromObj(interp_, obj, &val); - if (cc != TCL_OK) - { - throw tcl_error(interp_); - } - - return static_cast(val); -} - -result::operator double() const -{ - Tcl_Obj *obj = Tcl_GetObjResult(interp_); - - double val; - int cc = Tcl_GetDoubleFromObj(interp_, obj, &val); - if (cc != TCL_OK) - { - throw tcl_error(interp_); - } - - return val; -} - -result::operator int() const -{ - Tcl_Obj *obj = Tcl_GetObjResult(interp_); - - int val, cc; - cc = Tcl_GetIntFromObj(interp_, obj, &val); - if (cc != TCL_OK) - { - throw tcl_error(interp_); - } - - return val; -} - -result::operator long() const -{ - Tcl_Obj *obj = Tcl_GetObjResult(interp_); - - long val; - int cc; - cc = Tcl_GetLongFromObj(interp_, obj, &val); - if (cc != TCL_OK) - { - throw tcl_error(interp_); - } - - return val; -} - -result::operator string() const -{ - Tcl_Obj *obj = Tcl_GetObjResult(interp_); - return Tcl_GetString(obj); -} - -result::operator object() const -{ - return object(Tcl_GetObjResult(interp_)); -} - - -void details::set_result(Tcl_Interp *interp, bool b) -{ - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(b)); -} - -void details::set_result(Tcl_Interp *interp, int i) -{ - Tcl_SetObjResult(interp, Tcl_NewIntObj(i)); -} - -void details::set_result(Tcl_Interp *interp, long i) -{ - Tcl_SetObjResult(interp, Tcl_NewLongObj(i)); -} - -void details::set_result(Tcl_Interp *interp, double d) -{ - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(d)); -} - -void details::set_result(Tcl_Interp *interp, string const &s) -{ - Tcl_SetObjResult(interp, - Tcl_NewStringObj(s.data(), static_cast(s.size()))); -} - -void details::set_result(Tcl_Interp *interp, void *p) -{ - ostringstream ss; - ss << 'p' << p; - string s(ss.str()); - - Tcl_SetObjResult(interp, - Tcl_NewStringObj(s.data(), static_cast(s.size()))); -} - -void details::set_result(Tcl_Interp *interp, object const &o) -{ - Tcl_SetObjResult(interp, o.get_object()); -} - - -void details::check_params_no(int objc, int required) -{ - if (objc < required) - { - throw tcl_error("Too few arguments."); - } -} - -object details::get_var_params(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - int from, policies const &pol) -{ - object o; - if (pol.variadic_) - { - check_params_no(objc, from); - o.assign(objv + from, objv + objc); - } - else - { - check_params_no(objc, from + 1); - o.assign(objv[from]); - } - - o.set_interp(interp); - - return o; -} - - -namespace // anonymous -{ - -// map of polymorphic callbacks -typedef map > callback_interp_map; -typedef map callback_map; - -callback_map callbacks; -callback_map constructors; - -// map of call policies -typedef map policies_interp_map; -typedef map policies_map; - -policies_map call_policies; - -// map of object handlers -typedef map > class_interp_map; -typedef map class_handlers_map; - -class_handlers_map class_handlers; - - -// helper for finding call policies - returns true when found -bool find_policies(Tcl_Interp *interp, string const &cmdName, - policies_interp_map::iterator &piti) -{ - policies_map::iterator pit = call_policies.find(interp); - if (pit == call_policies.end()) - { - return false; - } - - piti = pit->second.find(cmdName); - return piti != pit->second.end(); -} - -extern "C" -int object_handler(ClientData cd, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[]); - -// helper function for post-processing call policies -// for both free functions (isMethod == false) -// and class methods (isMethod == true) -void post_process_policies(Tcl_Interp *interp, policies &pol, - Tcl_Obj * CONST objv[], bool isMethod) -{ - // check if it is a factory - if (!pol.factory_.empty()) - { - class_handlers_map::iterator it = class_handlers.find(interp); - if (it == class_handlers.end()) - { - throw tcl_error( - "Factory was registered for unknown class."); - } - - class_interp_map::iterator oit = it->second.find(pol.factory_); - if (oit == it->second.end()) - { - throw tcl_error( - "Factory was registered for unknown class."); - } - - class_handler_base *chb = oit->second.get(); - - // register a new command for the object returned - // by this factory function - // if everything went OK, the result is the address of the - // new object in the 'pXXX' form - // - the new command will be created with this name - - Tcl_CreateObjCommand(interp, - Tcl_GetString(Tcl_GetObjResult(interp)), - object_handler, static_cast(chb), 0); - } - - // process all declared sinks - // - unregister all object commands that envelopes the pointers - for (vector::iterator s = pol.sinks_.begin(); - s != pol.sinks_.end(); ++s) - { - if (isMethod == false) - { - // example: if there is a declared sink at parameter 3, - // and the Tcl command was: - // % fun par1 par2 PAR3 par4 - // then the index 3 correctly points into the objv array - - int index = *s; - Tcl_DeleteCommand(interp, Tcl_GetString(objv[index])); - } - else - { - // example: if there is a declared sink at parameter 3, - // and the Tcl command was: - // % $p method par1 par2 PAR3 par4 - // then the index 3 needs to be incremented - // in order correctly point into the 4th index of objv array - - int index = *s + 1; - Tcl_DeleteCommand(interp, Tcl_GetString(objv[index])); - } - } -} - -// actual functions handling various callbacks - -// generic callback handler -extern "C" -int callback_handler(ClientData, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[]) -{ - callback_map::iterator it = callbacks.find(interp); - if (it == callbacks.end()) - { - Tcl_SetResult(interp, - const_cast("Trying to invoke non-existent callback (wrong interpreter?)"), - TCL_STATIC); - return TCL_ERROR; - } - - string cmdName(Tcl_GetString(objv[0])); - callback_interp_map::iterator iti = it->second.find(cmdName); - if (iti == it->second.end()) - { - Tcl_SetResult(interp, - const_cast("Trying to invoke non-existent callback (wrong cmd name?)"), - TCL_STATIC); - return TCL_ERROR; - } - - policies_map::iterator pit = call_policies.find(interp); - if (pit == call_policies.end()) - { - Tcl_SetResult(interp, - const_cast("Trying to invoke callback with no known policies"), - TCL_STATIC); - return TCL_ERROR; - } - - policies_interp_map::iterator piti; - if (find_policies(interp, cmdName, piti) == false) - { - Tcl_SetResult(interp, - const_cast("Trying to invoke callback with no known policies"), - TCL_STATIC); - return TCL_ERROR; - } - - policies &pol = piti->second; - - try - { - iti->second->invoke(interp, objc, objv, pol); - - post_process_policies(interp, pol, objv, false); - } - catch (exception const &e) - { - Tcl_SetResult(interp, const_cast(e.what()), TCL_VOLATILE); - return TCL_ERROR; - } - catch (...) - { - Tcl_SetResult(interp, const_cast("Unknown error."), TCL_STATIC); - return TCL_ERROR; - } - - return TCL_OK; -} - -// generic "object" command handler -extern "C" -int object_handler(ClientData cd, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[]) -{ - // here, client data points to the singleton object - // which is responsible for managing commands for - // objects of a given type - - class_handler_base *chb = reinterpret_cast(cd); - - // the command name has the form 'pXXX' where XXX is the address - // of the "this" object - - string const str(Tcl_GetString(objv[0])); - istringstream ss(str); - char dummy; - void *p; - ss >> dummy >> p; - - try - { - string methodName(Tcl_GetString(objv[1])); - policies &pol = chb->get_policies(methodName); - - chb->invoke(p, interp, objc, objv, pol); - - post_process_policies(interp, pol, objv, true); - } - catch (exception const &e) - { - Tcl_SetResult(interp, const_cast(e.what()), TCL_VOLATILE); - return TCL_ERROR; - } - catch (...) - { - Tcl_SetResult(interp, const_cast("Unknown error."), TCL_STATIC); - return TCL_ERROR; - } - - return TCL_OK; -} - -// generic "constructor" command -extern "C" -int constructor_handler(ClientData cd, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[]) -{ - // here, client data points to the singleton object - // which is responsible for managing commands for - // objects of a given type - - class_handler_base *chb = reinterpret_cast(cd); - - callback_map::iterator it = constructors.find(interp); - if (it == constructors.end()) - { - Tcl_SetResult(interp, - const_cast("Trying to invoke non-existent callback (wrong interpreter?)"), - TCL_STATIC); - return TCL_ERROR; - } - - string className(Tcl_GetString(objv[0])); - callback_interp_map::iterator iti = it->second.find(className); - if (iti == it->second.end()) - { - Tcl_SetResult(interp, - const_cast("Trying to invoke non-existent callback (wrong class name?)"), - TCL_STATIC); - return TCL_ERROR; - } - - policies_interp_map::iterator piti; - if (find_policies(interp, className, piti) == false) - { - Tcl_SetResult(interp, - const_cast("Trying to invoke callback with no known policies"), - TCL_STATIC); - return TCL_ERROR; - } - - policies &pol = piti->second; - - try - { - iti->second->invoke(interp, objc, objv, pol); - - // if everything went OK, the result is the address of the - // new object in the 'pXXX' form - // - we can create a new command with this name - - Tcl_CreateObjCommand(interp, - Tcl_GetString(Tcl_GetObjResult(interp)), - object_handler, static_cast(chb), 0); - } - catch (exception const &e) - { - Tcl_SetResult(interp, const_cast(e.what()), TCL_VOLATILE); - return TCL_ERROR; - } - catch (...) - { - Tcl_SetResult(interp, const_cast("Unknown error."), TCL_STATIC); - return TCL_ERROR; - } - - return TCL_OK; -} - -} // namespace anonymous - -Tcl::details::no_init_type Tcl::no_init; - - -policies & policies::factory(string const &name) -{ - factory_ = name; - return *this; -} - -policies & policies::sink(int index) -{ - sinks_.push_back(index); - return *this; -} - -policies & policies::variadic() -{ - variadic_ = true; - return *this; -} - -policies Tcl::factory(string const &name) -{ - return policies().factory(name); -} - -policies Tcl::sink(int index) -{ - return policies().sink(index); -} - -policies Tcl::variadic() -{ - return policies().variadic(); -} - - -class_handler_base::class_handler_base() -{ - // default policies for the -delete command - policies_["-delete"] = policies(); -} - -void class_handler_base::register_method(string const &name, - shared_ptr ocb, policies const &p) -{ - methods_[name] = ocb; - policies_[name] = p; -} - -policies & class_handler_base::get_policies(string const &name) -{ - policies_map_type::iterator it = policies_.find(name); - if (it == policies_.end()) - { - throw tcl_error("Trying to use non-existent policy: " + name); - } - - return it->second; -} - - -object::object() - : interp_(0) -{ - obj_ = Tcl_NewObj(); - Tcl_IncrRefCount(obj_); -} - -object::object(bool b) - : interp_(0) -{ - obj_ = Tcl_NewBooleanObj(b); - Tcl_IncrRefCount(obj_); -} - -object::object(char const *buf, size_t size) - : interp_(0) -{ - obj_ = Tcl_NewByteArrayObj( - reinterpret_cast(buf), - static_cast(size)); - Tcl_IncrRefCount(obj_); -} - -object::object(double d) - : interp_(0) -{ - obj_ = Tcl_NewDoubleObj(d); - Tcl_IncrRefCount(obj_); -} - -object::object(int i) - : interp_(0) -{ - obj_ = Tcl_NewIntObj(i); - Tcl_IncrRefCount(obj_); -} - -object::object(long l) - : interp_(0) -{ - obj_ = Tcl_NewLongObj(l); - Tcl_IncrRefCount(obj_); -} - -object::object(char const *s) - : interp_(0) -{ - obj_ = Tcl_NewStringObj(s, -1); - Tcl_IncrRefCount(obj_); -} - -object::object(string const &s) - : interp_(0) -{ - obj_ = Tcl_NewStringObj(s.data(), static_cast(s.size())); - Tcl_IncrRefCount(obj_); -} - -object::object(Tcl_Obj *o, bool shared) - : interp_(0) -{ - init(o, shared); -} - -object::object(object const &other, bool shared) - : interp_(other.get_interp()) -{ - init(other.obj_, shared); -} - -void object::init(Tcl_Obj *o, bool shared) -{ - if (shared) - { - obj_ = o; - } - else - { - obj_ = Tcl_DuplicateObj(o); - } - Tcl_IncrRefCount(obj_); -} - -object::~object() -{ - Tcl_DecrRefCount(obj_); -} - -object & object::assign(bool b) -{ - Tcl_SetBooleanObj(obj_, b); - return *this; -} - -object & object::resize(size_t size) -{ - Tcl_SetByteArrayLength(obj_, static_cast(size)); - return *this; -} - -object & object::assign(char const *buf, size_t size) -{ - Tcl_SetByteArrayObj(obj_, - reinterpret_cast(buf), - static_cast(size)); - return *this; -} - -object & object::assign(double d) -{ - Tcl_SetDoubleObj(obj_, d); - return *this; -} - -object & object::assign(int i) -{ - Tcl_SetIntObj(obj_, i); - return *this; -} - -object & object::assign(long l) -{ - Tcl_SetLongObj(obj_, l); - return *this; -} - -object & object::assign(char const *s) -{ - Tcl_SetStringObj(obj_, s, -1); - return *this; -} - -object & object::assign(string const &s) -{ - Tcl_SetStringObj(obj_, s.data(), static_cast(s.size())); - return *this; -} - -object & object::assign(object const &other) -{ - object(other).swap(*this); - return *this; -} - -object & object::assign(Tcl_Obj *o) -{ - object(o).swap(*this); - return *this; -} - -object & object::swap(object &other) -{ - std::swap(obj_, other.obj_); - std::swap(interp_, other.interp_); - return *this; -} - -template <> -bool object::get(interpreter &i) const -{ - int retVal; - int res = Tcl_GetBooleanFromObj(i.get(), obj_, &retVal); - if (res != TCL_OK) - { - throw tcl_error(i.get()); - } - - return static_cast(retVal); -} - -template <> -vector object::get >(interpreter &) const -{ - size_t size; - char const *buf = get(size); - return vector(buf, buf + size); -} - -template <> -double object::get(interpreter &i) const -{ - double retVal; - int res = Tcl_GetDoubleFromObj(i.get(), obj_, &retVal); - if (res != TCL_OK) - { - throw tcl_error(i.get()); - } - - return retVal; -} - -template <> -int object::get(interpreter &i) const -{ - int retVal; - - int res = Tcl_GetIntFromObj(i.get(), obj_, &retVal); - if (res != TCL_OK) - { - throw tcl_error(i.get()); - } - - return retVal; -} - -template <> -long object::get(interpreter &i) const -{ - long retVal; - int res = Tcl_GetLongFromObj(i.get(), obj_, &retVal); - if (res != TCL_OK) - { - throw tcl_error(i.get()); - } - - return retVal; -} - -template <> -char const * object::get(interpreter &) const -{ - return get(); -} - -template <> -string object::get(interpreter &) const -{ - int len; - char const *buf = Tcl_GetStringFromObj(obj_, &len); - return string(buf, buf + len); -} - -char const * object::get() const -{ - return Tcl_GetString(obj_); -} - -char const * object::get(size_t &size) const -{ - int len; - unsigned char *buf = Tcl_GetByteArrayFromObj(obj_, &len); - size = len; - return const_cast(reinterpret_cast(buf)); -} - -size_t object::length(interpreter &i) const -{ - int len; - int res = Tcl_ListObjLength(i.get(), obj_, &len); - - if (res != TCL_OK) - { - throw tcl_error(i.get()); - } - - return static_cast(len); -} - -object object::at(interpreter &i, size_t index) const -{ - Tcl_Obj *o; - int res = Tcl_ListObjIndex(i.get(), obj_, static_cast(index), &o); - if (res != TCL_OK) - { - throw tcl_error(i.get()); - } - if (o == NULL) - { - throw tcl_error("Index out of range."); - } - - return object(o); -} - -object & object::append(interpreter &i, object const &o) -{ - int res = Tcl_ListObjAppendElement(i.get(), obj_, o.obj_); - if (res != TCL_OK) - { - throw tcl_error(i.get()); - } - - return *this; -} - -object & object::append_list(interpreter &i, object const &o) -{ - int res = Tcl_ListObjAppendList(i.get(), obj_, o.obj_); - if (res != TCL_OK) - { - throw tcl_error(i.get()); - } - - return *this; -} - -object & object::replace(interpreter &i, size_t index, size_t count, - object const &o) -{ - int res = Tcl_ListObjReplace(i.get(), obj_, - static_cast(index), static_cast(count), - 1, &(o.obj_)); - if (res != TCL_OK) - { - throw tcl_error(i.get()); - } - - return *this; -} - -object & object::replace_list(interpreter &i, size_t index, size_t count, - object const &o) -{ - int objc; - Tcl_Obj **objv; - - int res = Tcl_ListObjGetElements(i.get(), o.obj_, &objc, &objv); - if (res != TCL_OK) - { - throw tcl_error(i.get()); - } - - res = Tcl_ListObjReplace(i.get(), obj_, - static_cast(index), static_cast(count), - objc, objv); - if (res != TCL_OK) - { - throw tcl_error(i.get()); - } - - return *this; -} - -void object::set_interp(Tcl_Interp *interp) -{ - interp_ = interp; -} - -Tcl_Interp * object::get_interp() const -{ - return interp_; -} - - -interpreter::interpreter() -{ - interp_ = Tcl_CreateInterp(); - owner_ = true; -} - -interpreter::interpreter(Tcl_Interp *interp, bool owner) -{ - interp_ = interp; - owner_ = owner; -} - -interpreter::~interpreter() -{ - if (owner_) - { - // clear all callback info belonging to this interpreter - clear_definitions(interp_); - - Tcl_DeleteInterp(interp_); - } -} - -void interpreter::make_safe() -{ - int cc = Tcl_MakeSafe(interp_); - if (cc != TCL_OK) - { - throw tcl_error(interp_); - } -} - -result interpreter::eval(string const &script) -{ - int cc = Tcl_Eval(interp_, script.c_str()); - if (cc != TCL_OK) - { - throw tcl_error(interp_); - } - - return result(interp_); -} - -result interpreter::eval(istream &s) -{ - string str( - istreambuf_iterator(s.rdbuf()), - istreambuf_iterator() - ); - return eval(str); -} - -result interpreter::eval(object const &o) -{ - int cc = Tcl_EvalObjEx(interp_, o.get_object(), 0); - if (cc != TCL_OK) - { - throw tcl_error(interp_); - } - - return result(interp_); -} - -void interpreter::pkg_provide(string const &name, string const &version) -{ - int cc = Tcl_PkgProvide(interp_, name.c_str(), version.c_str()); - if (cc != TCL_OK) - { - throw tcl_error(interp_); - } -} - -void interpreter::create_alias(string const &cmd, - interpreter &targetInterp, string const &targetCmd) -{ - int cc = Tcl_CreateAlias(interp_, cmd.c_str(), - targetInterp.interp_, targetCmd.c_str(), 0, 0); - if (cc != TCL_OK) - { - throw tcl_error(interp_); - } -} - -void interpreter::clear_definitions(Tcl_Interp *interp) -{ - // delete all callbacks that were registered for given interpreter - - { - callback_map::iterator it = callbacks.find(interp); - if (it == callbacks.end()) - { - // no callbacks defined for this interpreter - return; - } - - callback_interp_map &imap = it->second; - for (callback_interp_map::iterator it2 = imap.begin(); - it2 != imap.end(); ++it2) - { - Tcl_DeleteCommand(interp, it2->first.c_str()); - } - - callbacks.erase(interp); - } - - // delete all constructors - - { - callback_map::iterator it = constructors.find(interp); - if (it == constructors.end()) - { - // no callbacks defined for this interpreter - return; - } - - callback_interp_map &imap = it->second; - for (callback_interp_map::iterator it2 = imap.begin(); - it2 != imap.end(); ++it2) - { - Tcl_DeleteCommand(interp, it2->first.c_str()); - } - - callbacks.erase(interp); - } - - // delete all call policies - - call_policies.erase(interp); - - // delete all object handlers - // (we have to assume that all living objects were destroyed, - // otherwise Bad Things will happen) - - class_handlers.erase(interp); -} - -void interpreter::add_function(string const &name, - shared_ptr cb, policies const &p) -{ - Tcl_CreateObjCommand(interp_, name.c_str(), - callback_handler, 0, 0); - - callbacks[interp_][name] = cb; - call_policies[interp_][name] = p; -} - -void interpreter::add_class(string const &name, - shared_ptr chb) -{ - class_handlers[interp_][name] = chb; -} - -void interpreter::add_constructor(string const &name, - shared_ptr chb, shared_ptr cb, - policies const &p) -{ - Tcl_CreateObjCommand(interp_, name.c_str(), - constructor_handler, static_cast(chb.get()), 0); - - constructors[interp_][name] = cb; - call_policies[interp_][name] = p; -} - - -int tcl_cast::from(Tcl_Interp *interp, Tcl_Obj *obj) -{ - int res; - int cc = Tcl_GetIntFromObj(interp, obj, &res); - if (cc != TCL_OK) - { - throw tcl_error(interp); - } - - return res; -} - -long tcl_cast::from(Tcl_Interp *interp, Tcl_Obj *obj) -{ - long res; - int cc = Tcl_GetLongFromObj(interp, obj, &res); - if (cc != TCL_OK) - { - throw tcl_error(interp); - } - - return res; -} - -bool tcl_cast::from(Tcl_Interp *interp, Tcl_Obj *obj) -{ - int res; - int cc = Tcl_GetBooleanFromObj(interp, obj, &res); - if (cc != TCL_OK) - { - throw tcl_error(interp); - } - - return res != 0; -} - -double tcl_cast::from(Tcl_Interp *interp, Tcl_Obj *obj) -{ - double res; - int cc = Tcl_GetDoubleFromObj(interp, obj, &res); - if (cc != TCL_OK) - { - throw tcl_error(interp); - } - - return res; -} - -string tcl_cast::from(Tcl_Interp *, Tcl_Obj *obj) -{ - return Tcl_GetString(obj); -} - -char const * tcl_cast::from(Tcl_Interp *, Tcl_Obj *obj) -{ - return Tcl_GetString(obj); -} - -object tcl_cast::from(Tcl_Interp *interp, Tcl_Obj *obj) -{ - object o(obj); - o.set_interp(interp); - - return o; -} diff --git a/cpptcl.h b/cpptcl.h deleted file mode 100644 index e718f39..0000000 --- a/cpptcl.h +++ /dev/null @@ -1,871 +0,0 @@ -// -// Copyright (C) 2004-2006, Maciej Sobczak -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// - -#ifndef CPPTCL_INCLUDED -#define CPPTCL_INCLUDED - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std::placeholders; - -namespace Tcl -{ - -// exception class used for reporting all Tcl errors - -class tcl_error : public std::runtime_error -{ -public: - explicit tcl_error(std::string const &msg) - : std::runtime_error(msg) {} - explicit tcl_error(Tcl_Interp *interp) - : std::runtime_error(Tcl_GetString(Tcl_GetObjResult(interp))) {} -}; - -// call policies - -struct policies -{ - policies() : variadic_(false) {} - - policies & factory(std::string const &name); - - // note: this is additive - policies & sink(int index); - - policies & variadic(); - - std::string factory_; - std::vector sinks_; - bool variadic_; -}; - -// syntax short-cuts -policies factory(std::string const &name); -policies sink(int index); -policies variadic(); - - -class interpreter; -class object; - -namespace details -{ - -// wrapper for the evaluation result -class result -{ -public: - result(Tcl_Interp *interp); - - operator bool() const; - operator double() const; - operator int() const; - operator long() const; - operator std::string() const; - operator object() const; - -private: - Tcl_Interp *interp_; -}; - -// helper functions used to set the result value - -void set_result(Tcl_Interp *interp, bool b); -void set_result(Tcl_Interp *interp, int i); -void set_result(Tcl_Interp *interp, long i); -void set_result(Tcl_Interp *interp, double d); -void set_result(Tcl_Interp *interp, std::string const &s); -void set_result(Tcl_Interp *interp, void *p); -void set_result(Tcl_Interp *interp, object const &o); - -// helper functor for converting Tcl objects to the given type -#include "details/conversions.h" - -// dispatchers able to capture (or ignore) the result -#include "details/dispatchers.h" - -// helper for checking for required number of parameters -// (throws tcl_error when not met) -void check_params_no(int objc, int required); - -// helper for gathering optional params in variadic functions -object get_var_params(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - int from, policies const &pol); - -// the callback_base is used to store callback handlers in a polynorphic map -class callback_base -{ -public: - virtual ~callback_base() {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &pol) = 0; -}; - - -// base class for object command handlers -// and for class handlers -class object_cmd_base -{ -public: - // destructor not needed, but exists to shut up the compiler warnings - virtual ~object_cmd_base() {} - - virtual void invoke(void *p, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &pol) = 0; -}; - -// base class for all class handlers, still abstract -class class_handler_base : public object_cmd_base -{ -public: - typedef std::map policies_map_type; - - class_handler_base(); - - void register_method(std::string const &name, - std::shared_ptr ocb, policies const &p); - - policies & get_policies(std::string const &name); - -protected: - typedef std::map< - std::string, - std::shared_ptr - > method_map_type; - - // a map of methods for the given class - method_map_type methods_; - - policies_map_type policies_; -}; - -// class handler - responsible for executing class methods -template -class class_handler : public class_handler_base -{ -public: - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &pol) - { - C * p = static_cast(pv); - - if (objc < 2) - { - throw tcl_error("Too few arguments."); - } - - std::string methodName(Tcl_GetString(objv[1])); - - if (methodName == "-delete") - { - Tcl_DeleteCommand(interp, Tcl_GetString(objv[0])); - delete p; - return; - } - - // dispatch on the method name - - method_map_type::iterator it = methods_.find(methodName); - if (it == methods_.end()) - { - throw tcl_error("Method " + methodName + " not found."); - } - - it->second->invoke(pv, interp, objc, objv, pol); - } -}; - - -// factory functions for creating class objects -#include "details/constructors.h" - -// actual callback envelopes -#include "details/callbacks.h" - -// actual method envelopes -#include "details/methods.h" - -// helper meta function for figuring appropriate constructor callback -#include "details/metahelpers.h" - - -// this class is used to provide the "def" interface for defining -// class member functions - -template -class class_definer -{ -public: - class_definer(std::shared_ptr > ch) : ch_(ch) {} - - template - class_definer & def(std::string const &name, R (C::*f)(), - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method0(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, R (C::*f)() const, - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method0(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, R (C::*f)(T1), - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method1(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, R (C::*f)(T1) const, - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method1(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, R (C::*f)(T1, T2), - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method2(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, R (C::*f)(T1, T2) const, - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method2(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, R (C::*f)(T1, T2, T3), - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method3(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, R (C::*f)(T1, T2, T3) const, - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method3(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, R (C::*f)(T1, T2, T3, T4), - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method4(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, - R (C::*f)(T1, T2, T3, T4) const, - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method4(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, - R (C::*f)(T1, T2, T3, T4, T5), policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method5(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, - R (C::*f)(T1, T2, T3, T4, T5) const, policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method5(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, - R (C::*f)(T1, T2, T3, T4, T5, T6), policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method6(f)), - p); - return *this; - } - - template - class_definer & def(std::string const &name, - R (C::*f)(T1, T2, T3, T4, T5, T6) const, - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method6(f)), - p); - return *this; - } - - template - class_definer & def(std::string const &name, - R (C::*f)(T1, T2, T3, T4, T5, T6, T7), - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method7(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, - R (C::*f)(T1, T2, T3, T4, T5, T6, T7) const, - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method7(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, - R (C::*f)(T1, T2, T3, T4, T5, T6, T7, T8), - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method8(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, - R (C::*f)(T1, T2, T3, T4, T5, T6, T7, T8) const, - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method8(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, - R (C::*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9), - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method9(f)), p); - return *this; - } - - template - class_definer & def(std::string const &name, - R (C::*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9) const, - policies const &p = policies()) - { - ch_->register_method(name, - std::shared_ptr( - new details::method9(f)), p); - return *this; - } - -private: - std::shared_ptr > ch_; -}; - -} // namespace details - - -// init type for defining class constructors -template -class init {}; - -// no_init type and object - to define classes without constructors -namespace details -{ - struct no_init_type {}; -} // namespace details -extern details::no_init_type no_init; - - -// interpreter wrapper -class interpreter -{ -public: - interpreter(); - interpreter(Tcl_Interp *, bool owner = true); - ~interpreter(); - - void make_safe(); - - Tcl_Interp * get() const { return interp_; } - - // free function definitions - - template - void def(std::string const &name, R (*f)(), - policies const &p = policies()) - { - add_function(name, - std::shared_ptr( - new details::callback0(f)), p); - } - - template - void def(std::string const &name, R (*f)(T1), - policies const &p = policies()) - { - add_function(name, - std::shared_ptr( - new details::callback1(f)), p); - } - - template - void def(std::string const &name, R (*f)(T1, T2), - policies const &p = policies()) - { - add_function(name, - std::shared_ptr( - new details::callback2(f)), p); - } - - template - void def(std::string const &name, R (*f)(T1, T2, T3), - policies const &p = policies()) - { - add_function(name, - std::shared_ptr( - new details::callback3(f)), p); - } - - template - void def(std::string const &name, R (*f)(T1, T2, T3, T4), - policies const &p = policies()) - { - add_function(name, - std::shared_ptr( - new details::callback4(f)), p); - } - - template - void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5), - policies const &p = policies()) - { - add_function(name, - std::shared_ptr( - new details::callback5(f)), p); - } - - template - void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5, T6), - policies const &p = policies()) - { - add_function(name, - std::shared_ptr( - new details::callback6(f)), p); - } - - template - void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5, T6, T7), - policies const &p = policies()) - { - add_function(name, - std::shared_ptr( - new details::callback7(f)), p); - } - - template - void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5, T6, T7, T8), - policies const &p = policies()) - { - add_function(name, - std::shared_ptr( - new details::callback8(f)), p); - } - - template - void def(std::string const &name, - R (*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9), - policies const &p = policies()) - { - add_function(name, - std::shared_ptr( - new details::callback9(f)), p); - } - - - // class definitions - - template - details::class_definer class_(std::string const &name) - { - std::shared_ptr > ch( - new details::class_handler()); - - add_class(name, ch); - - add_constructor(name, ch, - std::shared_ptr( - new details::callback0(&details::construct< - C, void, void, void, void, void, void, void, - void, void>::doit))); - - return details::class_definer(ch); - } - - template - details::class_definer class_(std::string const &name, - init const &, - policies const &p = policies()) - { - typedef typename details::get_callback_type_for_construct< - C, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type - callback_type; - - std::shared_ptr > ch( - new details::class_handler()); - - add_class(name, ch); - - add_constructor(name, ch, - std::shared_ptr( - new callback_type(&details::construct< - C, T1, T2, T3, T4, T5, T6, T7, T8, T9>::doit)), p); - - return details::class_definer(ch); - } - - template - details::class_definer class_( - std::string const &name, details::no_init_type const &) - { - std::shared_ptr > ch( - new details::class_handler()); - - add_class(name, ch); - - return details::class_definer(ch); - } - - // free script evaluation - details::result eval(std::string const &script); - details::result eval(std::istream &s); - - details::result eval(object const &o); - - // the InputIterator should give object& or Tcl_Obj* when dereferenced - template - details::result eval(InputIterator first, InputIterator last); - - // create alias from the *this interpreter to the target interpreter - void create_alias(std::string const &cmd, - interpreter &targetInterp, std::string const &targetCmd); - - // register a package info (useful when defining packages) - void pkg_provide(std::string const &name, std::string const &version); - - // helper for cleaning up callbacks in non-managed interpreters - static void clear_definitions(Tcl_Interp *); - -private: - - // copy not supported - interpreter(const interpreter &); - void operator=(const interpreter &); - - void add_function(std::string const &name, - std::shared_ptr cb, - policies const &p = policies()); - - void add_class(std::string const &name, - std::shared_ptr chb); - - void add_constructor(std::string const &name, - std::shared_ptr chb, - std::shared_ptr cb, - policies const &p = policies()); - - Tcl_Interp *interp_; - bool owner_; -}; - - -// object wrapper -class object -{ -public: - - // constructors - - object(); - - explicit object(bool b); - object(char const *buf, size_t size); // byte array - explicit object(double b); - explicit object(int i); - - // list creation - // the InputIterator should give object& or Tcl_Obj* when dereferenced - template - object(InputIterator first, InputIterator last) - : interp_(0) - { - std::vector v; - fill_vector(v, first, last); - obj_ = Tcl_NewListObj(static_cast(v.size()), - v.empty() ? NULL : &v[0]); - Tcl_IncrRefCount(obj_); - } - - explicit object(long i); - explicit object(char const *s); // string construction - explicit object(std::string const &s); // string construction - - explicit object(Tcl_Obj *o, bool shared = false); - - object(object const &other, bool shared = false); - ~object(); - - // assignment - - object & assign(bool b); - object & resize(size_t size); // byte array resize - object & assign(char const *buf, size_t size); // byte array assignment - object & assign(double d); - object & assign(int i); - - // list assignment - // the InputIterator should give Tcl_Obj* or object& when dereferenced - template - object & assign(InputIterator first, InputIterator last) - { - std::vector v; - fill_vector(v, first, last); - Tcl_SetListObj(obj_, static_cast(v.size()), - v.empty() ? NULL : &v[0]); - return *this; - } - - object & assign(long l); - object & assign(char const *s); // string assignment - object & assign(std::string const &s); // string assignment - object & assign(object const &o); - object & assign(Tcl_Obj *o); - - object & operator=(bool b) { return assign(b); } - object & operator=(double d) { return assign(d); } - object & operator=(int i) { return assign(i); } - object & operator=(long l) { return assign(l); } - object & operator=(char const *s) { return assign(s); } - object & operator=(std::string const &s) { return assign(s); } - - object & operator=(object const &o) { return assign(o); } - object & swap(object &other); - - // (logically) non-modifying members - - template - T get(interpreter &i) const; - - char const * get() const; // string get - char const * get(size_t &size) const; // byte array get - - size_t length(interpreter &i) const; // returns list length - object at(interpreter &i, size_t index) const; - - Tcl_Obj * get_object() const { return obj_; } - - // modifying members - - object & append(interpreter &i, object const &o); - object & append_list(interpreter &i, object const &o); - - // list replace - // the InputIterator should give Tcl_Obj* or object& when dereferenced - template - object & replace(interpreter &i, size_t index, size_t count, - InputIterator first, InputIterator last) - { - std::vector v; - fill_vector(v, first, last); - int res = Tcl_ListObjReplace(i.get(), obj_, - static_cast(index), static_cast(count), - static_cast(v.size()), v.empty() ? NULL : &v[0]); - if (res != TCL_OK) - { - throw tcl_error(i.get()); - } - - return *this; - } - - object & replace(interpreter &i, size_t index, size_t count, - object const &o); - object & replace_list(interpreter &i, size_t index, size_t count, - object const &o); - - // helper functions for piggy-backing interpreter info - void set_interp(Tcl_Interp *interp); - Tcl_Interp * get_interp() const; - - // helper function, also used from interpreter::eval - template - static void fill_vector(std::vector &v, - InputIterator first, InputIterator last) - { - for (; first != last; ++first) - { - object o(*first, true); - v.push_back(o.obj_); - } - } - -private: - - // helper function used from copy constructors - void init(Tcl_Obj *o, bool shared); - - Tcl_Obj *obj_; - Tcl_Interp *interp_; -}; - -// available specializations for object::get -template <> bool object::get(interpreter &i) const; -template <> double object::get(interpreter &i) const; -template <> int object::get(interpreter &i) const; -template <> long object::get(interpreter &i) const; -template <> char const * object::get(interpreter &i) const; -template <> std::string object::get(interpreter &i) const; -template <> -std::vector object::get >(interpreter &i) const; - -// the InputIterator should give object& or Tcl_Obj* when dereferenced -template -details::result interpreter::eval(InputIterator first, InputIterator last) -{ - std::vector v; - object::fill_vector(v, first, last); - int cc = Tcl_EvalObjv(interp_, - static_cast(v.size()), v.empty() ? NULL : &v[0], 0); - if (cc != TCL_OK) - { - throw tcl_error(interp_); - } - - return details::result(interp_); -} - -namespace details -{ - -// additional callback envelopes for variadic functions -#include "details/callbacks_v.h" - -// additional method envelopes for variadic methods -#include "details/methods_v.h" - -} // namespace details - -} // namespace Tcl - - -// macro for defining loadable module entry point -// - used for extending Tcl interpreter - -#define CPPTCL_MODULE(name, i) void name##_cpptcl_Init(Tcl::interpreter &i); \ - extern "C" int name##_Init(Tcl_Interp *interp) \ - { \ - Tcl::interpreter i(interp, false); \ - name##_cpptcl_Init(i); \ - return TCL_OK; \ - } \ - void name##_cpptcl_Init(Tcl::interpreter &i) - - -#endif // CPPTCL_INCLUDED diff --git a/data/pattern.dat b/data/pattern.dat index 0c951c3..a21a9a2 100644 Binary files a/data/pattern.dat and b/data/pattern.dat differ diff --git a/details/callbacks.h b/details/callbacks.h deleted file mode 100644 index 9f7f767..0000000 --- a/details/callbacks.h +++ /dev/null @@ -1,273 +0,0 @@ -// -// Copyright (C) 2004-2006, Maciej Sobczak -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// - -// Note: this file is not supposed to be a stand-alone header - - -template -class callback0 : public callback_base -{ - typedef R (*functor_type)(); - -public: - callback0(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int, Tcl_Obj * CONST [], - policies const &) - { - dispatch::do_dispatch(interp, f_); - } - -private: - functor_type f_; -}; - -template -class callback1 : public callback_base -{ - typedef R (*functor_type)(T1); - -public: - callback1(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &) - { - check_params_no(objc, 2); - - dispatch::template do_dispatch(interp, f_, - tcl_cast::from(interp, objv[1])); - } - -private: - functor_type f_; -}; - -template -class callback2 : public callback_base -{ - typedef R (*functor_type)(T1, T2); - -public: - callback2(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &) - { - check_params_no(objc, 3); - - dispatch::template do_dispatch(interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2])); - } - -private: - functor_type f_; -}; - -template -class callback3 : public callback_base -{ - typedef R (*functor_type)(T1, T2, T3); - -public: - callback3(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &) - { - check_params_no(objc, 4); - - dispatch::template do_dispatch(interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3])); - } - -private: - functor_type f_; -}; - -template -class callback4 : public callback_base -{ - typedef R (*functor_type)(T1, T2, T3, T4); - -public: - callback4(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &) - { - check_params_no(objc, 5); - - dispatch::template do_dispatch(interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4])); - } - -private: - functor_type f_; -}; - -template -class callback5 : public callback_base -{ - typedef R (*functor_type)(T1, T2, T3, T4, T5); - -public: - callback5(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &) - { - check_params_no(objc, 6); - - dispatch::template do_dispatch(interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5])); - } - -private: - functor_type f_; -}; - -template -class callback6 : public callback_base -{ - typedef R (*functor_type)(T1, T2, T3, T4, T5, T6); - -public: - callback6(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &) - { - check_params_no(objc, 7); - - dispatch::template do_dispatch( - interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6])); - } - -private: - functor_type f_; -}; - -template -class callback7 : public callback_base -{ - typedef R (*functor_type)(T1, T2, T3, T4, T5, T6, T7); - -public: - callback7(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &) - { - check_params_no(objc, 8); - - dispatch::template do_dispatch( - interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7])); - } - -private: - functor_type f_; -}; - -template -class callback8 : public callback_base -{ - typedef R (*functor_type)(T1, T2, T3, T4, T5, T6, T7, T8); - -public: - callback8(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &) - { - check_params_no(objc, 9); - - dispatch::template do_dispatch( - interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - tcl_cast::from(interp, objv[8])); - } - -private: - functor_type f_; -}; - -template -class callback9 : public callback_base -{ - typedef R (*functor_type)(T1, T2, T3, T4, T5, T6, T7, T8, T9); - -public: - callback9(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &) - { - check_params_no(objc, 10); - - dispatch::template do_dispatch< - T1, T2, T3, T4, T5, T6, T7, T8, T9>(interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - tcl_cast::from(interp, objv[8]), - tcl_cast::from(interp, objv[9])); - } - -private: - functor_type f_; -}; diff --git a/details/callbacks_v.h b/details/callbacks_v.h deleted file mode 100644 index 6432531..0000000 --- a/details/callbacks_v.h +++ /dev/null @@ -1,267 +0,0 @@ -// -// Copyright (C) 2004-2006, Maciej Sobczak -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// - -// Note: this file is not supposed to be a stand-alone header - - -template -class callback1 : public callback_base -{ - typedef object const & T1; - typedef R (*functor_type)(T1); - enum { var_start = 1 }; - -public: - callback1(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &pol) - { - object t1 = get_var_params(interp, objc, objv, var_start, pol); - dispatch::template do_dispatch(interp, f_, - t1); - } - -private: - functor_type f_; -}; - -template -class callback2 : public callback_base -{ - typedef object const & T2; - typedef R (*functor_type)(T1, T2); - enum { var_start = 2 }; - -public: - callback2(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &pol) - { - object t2 = get_var_params(interp, objc, objv, var_start, pol); - dispatch::template do_dispatch(interp, f_, - tcl_cast::from(interp, objv[1]), - t2); - } - -private: - functor_type f_; -}; - -template -class callback3 : public callback_base -{ - typedef object const & T3; - typedef R (*functor_type)(T1, T2, T3); - enum { var_start = 3 }; - -public: - callback3(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &pol) - { - object t3 = get_var_params(interp, objc, objv, var_start, pol); - dispatch::template do_dispatch(interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - t3); - } - -private: - functor_type f_; -}; - -template -class callback4 : public callback_base -{ - typedef object const & T4; - typedef R (*functor_type)(T1, T2, T3, T4); - enum { var_start = 4 }; - -public: - callback4(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &pol) - { - object t4 = get_var_params(interp, objc, objv, var_start, pol); - dispatch::template do_dispatch(interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - t4); - } - -private: - functor_type f_; -}; - -template -class callback5 : public callback_base -{ - typedef object const & T5; - typedef R (*functor_type)(T1, T2, T3, T4, T5); - enum { var_start = 5 }; - -public: - callback5(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &pol) - { - object t5 = get_var_params(interp, objc, objv, var_start, pol); - dispatch::template do_dispatch( - interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - t5); - } - -private: - functor_type f_; -}; - -template -class callback6 : public callback_base -{ - typedef object const & T6; - typedef R (*functor_type)(T1, T2, T3, T4, T5, T6); - enum { var_start = 6 }; - -public: - callback6(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &pol) - { - object t6 = get_var_params(interp, objc, objv, var_start, pol); - dispatch::template do_dispatch( - interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - t6); - } - -private: - functor_type f_; -}; - -template -class callback7 - : public callback_base -{ - typedef object const & T7; - typedef R (*functor_type)(T1, T2, T3, T4, T5, T6, T7); - enum { var_start = 7 }; - -public: - callback7(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &pol) - { - object t7 = get_var_params(interp, objc, objv, var_start, pol); - dispatch::template do_dispatch( - interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - t7); - } - -private: - functor_type f_; -}; - -template -class callback8 - : public callback_base -{ - typedef object const & T8; - typedef R (*functor_type)(T1, T2, T3, T4, T5, T6, T7, T8); - enum { var_start = 8 }; - -public: - callback8(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &pol) - { - object t8 = get_var_params(interp, objc, objv, var_start, pol); - dispatch::template do_dispatch( - interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - t8); - } - -private: - functor_type f_; -}; - -template -class callback9 - : public callback_base -{ - typedef object const & T9; - typedef R (*functor_type)(T1, T2, T3, T4, T5, T6, T7, T8, T9); - enum { var_start = 9 }; - -public: - callback9(functor_type f) : f_(f) {} - - virtual void invoke(Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - policies const &pol) - { - object t9 = get_var_params(interp, objc, objv, var_start, pol); - dispatch::template do_dispatch< - T1, T2, T3, T4, T5, T6, T7, T8, T9>( - interp, f_, - tcl_cast::from(interp, objv[1]), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - tcl_cast::from(interp, objv[8]), - t9); - } - -private: - functor_type f_; -}; diff --git a/details/constructors.h b/details/constructors.h deleted file mode 100644 index 130d40f..0000000 --- a/details/constructors.h +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright (C) 2004-2006, Maciej Sobczak -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// - -// Note: this file is not supposed to be a stand-alone header - - -template -struct construct -{ - static C * doit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, - T8 t8, T9 t9) - { return new C(t1, t2, t3, t4, t5, t6, t7, t8, t9); } -}; - -template -struct construct -{ - static C * doit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) - { return new C(t1, t2, t3, t4, t5, t6, t7, t8); } -}; - -template -struct construct -{ - static C * doit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) - { return new C(t1, t2, t3, t4, t5, t6, t7); } -}; - -template -struct construct -{ - static C * doit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) - { return new C(t1, t2, t3, t4, t5, t6); } -}; - -template -struct construct -{ - static C * doit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) - { return new C(t1, t2, t3, t4, t5); } -}; - -template -struct construct -{ - static C * doit(T1 t1, T2 t2, T3 t3, T4 t4) - { return new C(t1, t2, t3, t4); } -}; - -template -struct construct -{ - static C * doit(T1 t1, T2 t2, T3 t3) - { return new C(t1, t2, t3); } -}; - -template -struct construct -{ - static C * doit(T1 t1, T2 t2) - { return new C(t1, t2); } -}; - -template -struct construct -{ - static C * doit(T1 t1) - { return new C(t1); } -}; - -template -struct construct -{ - static C * doit() - { return new C(); } -}; diff --git a/details/conversions.h b/details/conversions.h deleted file mode 100644 index 9d7d21e..0000000 --- a/details/conversions.h +++ /dev/null @@ -1,101 +0,0 @@ -// -// Copyright (C) 2004-2006, Maciej Sobczak -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// - -// Note: this file is not supposed to be a stand-alone header - - -// helper functor for converting Tcl objects to the given type -// (it is a struct instead of function, -// because I need to partially specialize it) - -template -struct tcl_cast; - -template -struct tcl_cast -{ - static T * from(Tcl_Interp *, Tcl_Obj *obj) - { - std::string s(Tcl_GetString(obj)); - if (s.size() == 0) - { - throw tcl_error("Expected pointer value, got empty string."); - } - - if (s[0] != 'p') - { - throw tcl_error("Expected pointer value."); - } - - std::istringstream ss(s); - char dummy; - void *p; - ss >> dummy >> p; - - return static_cast(p); - } -}; - -// the following partial specialization is to strip reference -// (it returns a temporary object of the underlying type, which -// can be bound to the const-ref parameter of the actual function) - -template -struct tcl_cast -{ - static T from(Tcl_Interp *interp, Tcl_Obj *obj) - { - return tcl_cast::from(interp, obj); - } -}; - - -// the following specializations are implemented - -template <> -struct tcl_cast -{ - static int from(Tcl_Interp *, Tcl_Obj *); -}; - -template <> -struct tcl_cast -{ - static long from(Tcl_Interp *, Tcl_Obj *); -}; - -template <> -struct tcl_cast -{ - static bool from(Tcl_Interp *, Tcl_Obj *); -}; - -template <> -struct tcl_cast -{ - static double from(Tcl_Interp *, Tcl_Obj *); -}; - -template <> -struct tcl_cast -{ - static std::string from(Tcl_Interp *, Tcl_Obj *); -}; - -template <> -struct tcl_cast -{ - static char const * from(Tcl_Interp *, Tcl_Obj *); -}; - -template <> -struct tcl_cast -{ - static object from(Tcl_Interp *, Tcl_Obj *); -}; diff --git a/details/dispatchers.h b/details/dispatchers.h deleted file mode 100644 index 5cd2e61..0000000 --- a/details/dispatchers.h +++ /dev/null @@ -1,181 +0,0 @@ -// -// Copyright (C) 2004-2006, Maciej Sobczak -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// - -// Note: this file is not supposed to be a stand-alone header - - -// the dispatch class is used to execute the callback functor and to -// capture its return value -// further dispatch specialization ignores the res - -template -struct dispatch -{ - template - static void do_dispatch(Tcl_Interp *interp, Functor f) - { - R res = f(); - set_result(interp, res); - } - - template - static void do_dispatch(Tcl_Interp *interp, Functor f, T1 t1) - { - R res = f(t1); - set_result(interp, res); - } - - template - static void do_dispatch(Tcl_Interp *interp, Functor f, T1 t1, T2 t2) - { - R res = f(t1, t2); - set_result(interp, res); - } - - template - static void do_dispatch(Tcl_Interp *interp, Functor f, - T1 t1, T2 t2, T3 t3) - { - R res = f(t1, t2, t3); - set_result(interp, res); - } - - template - static void do_dispatch(Tcl_Interp *interp, Functor f, - T1 t1, T2 t2, T3 t3, T4 t4) - { - R res = f(t1, t2, t3, t4); - set_result(interp, res); - } - - template - static void do_dispatch(Tcl_Interp *interp, Functor f, - T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) - { - R res = f(t1, t2, t3, t4, t5); - set_result(interp, res); - } - - template - static void do_dispatch(Tcl_Interp *interp, Functor f, - T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) - { - R res = f(t1, t2, t3, t4, t5, t6); - set_result(interp, res); - } - - template - static void do_dispatch(Tcl_Interp *interp, Functor f, - T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) - { - R res = f(t1, t2, t3, t4, t5, t6, t7); - set_result(interp, res); - } - - template - static void do_dispatch(Tcl_Interp *interp, Functor f, - T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) - { - R res = f(t1, t2, t3, t4, t5, t6, t7, t8); - set_result(interp, res); - } - - template - static void do_dispatch(Tcl_Interp *interp, Functor f, - T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9) - { - R res = f(t1, t2, t3, t4, t5, t6, t7, t8, t9); - set_result(interp, res); - } -}; - -template <> -struct dispatch -{ - template - static void do_dispatch(Tcl_Interp *, Functor f) - { - f(); - } - - template - static void do_dispatch(Tcl_Interp *, Functor f, T1 t1) - { - f(t1); - } - - template - static void do_dispatch(Tcl_Interp *, Functor f, T1 t1, T2 t2) - { - f(t1, t2); - } - - template - static void do_dispatch(Tcl_Interp *, Functor f, - T1 t1, T2 t2, T3 t3) - { - f(t1, t2, t3); - } - - template - static void do_dispatch(Tcl_Interp *, Functor f, - T1 t1, T2 t2, T3 t3, T4 t4) - { - f(t1, t2, t3, t4); - } - - template - static void do_dispatch(Tcl_Interp *, Functor f, - T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) - { - f(t1, t2, t3, t4, t5); - } - - template - static void do_dispatch(Tcl_Interp *, Functor f, - T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) - { - f(t1, t2, t3, t4, t5, t6); - } - - template - static void do_dispatch(Tcl_Interp *, Functor f, - T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) - { - f(t1, t2, t3, t4, t5, t6, t7); - } - - template - static void do_dispatch(Tcl_Interp *, Functor f, - T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) - { - f(t1, t2, t3, t4, t5, t6, t7, t8); - } - - template - static void do_dispatch(Tcl_Interp *, Functor f, - T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9) - { - f(t1, t2, t3, t4, t5, t6, t7, t8, t9); - } -}; diff --git a/details/metahelpers.h b/details/metahelpers.h deleted file mode 100644 index 7dc3400..0000000 --- a/details/metahelpers.h +++ /dev/null @@ -1,86 +0,0 @@ -// -// Copyright (C) 2004-2006, Maciej Sobczak -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// - -// Note: this file is not supposed to be a stand-alone header - - -template -struct get_callback_type_for_construct -{ - typedef callback9 type; -}; - -template -struct get_callback_type_for_construct< - C, T1, T2, T3, T4, T5, T6, T7, T8, void> -{ - typedef callback8 type; -}; - -template -struct get_callback_type_for_construct< - C, T1, T2, T3, T4, T5, T6, T7, void, void> -{ - typedef callback7 type; -}; - -template -struct get_callback_type_for_construct< - C, T1, T2, T3, T4, T5, T6, void, void, void> -{ - typedef callback6 type; -}; - -template -struct get_callback_type_for_construct< - C, T1, T2, T3, T4, T5, void, void, void, void> -{ - typedef callback5 type; -}; - -template -struct get_callback_type_for_construct< - C, T1, T2, T3, T4, void, void, void, void, void> -{ - typedef callback4 type; -}; - -template -struct get_callback_type_for_construct< - C, T1, T2, T3, void, void, void, void, void, void> -{ - typedef callback3 type; -}; - -template -struct get_callback_type_for_construct< - C, T1, T2, void, void, void, void, void, void, void> -{ - typedef callback2 type; -}; - -template -struct get_callback_type_for_construct< - C, T1, void, void, void, void, void, void, void, void> -{ - typedef callback1 type; -}; - -template -struct get_callback_type_for_construct< - C, void, void, void, void, void, void, void, void, void> -{ - typedef callback0 type; -}; diff --git a/details/methods.h b/details/methods.h deleted file mode 100644 index 8410c80..0000000 --- a/details/methods.h +++ /dev/null @@ -1,452 +0,0 @@ -// -// Copyright (C) 2004-2006, Maciej Sobczak -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// - -// Note: this file is not supposed to be a stand-alone header - - -template -class method0 : public object_cmd_base -{ - typedef R (C::*mem_type)(); - typedef R (C::*cmem_type)() const; - -public: - method0(mem_type f) : f_(f), cmem_(false) {} - method0(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int, Tcl_Obj * CONST [], policies const &) - { - C *p = static_cast(pv); - if (cmem_) - { - dispatch::do_dispatch(interp, std::bind(cf_, p)); - } - else - { - dispatch::do_dispatch(interp, std::bind(f_, p)); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method1 : public object_cmd_base -{ - typedef R (C::*mem_type)(T1); - typedef R (C::*cmem_type)(T1) const; - -public: - method1(mem_type f) : f_(f), cmem_(false) {} - method1(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &) - { - check_params_no(objc, 3); - - C *p = static_cast(pv); - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1), - tcl_cast::from(interp, objv[2])); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1), - tcl_cast::from(interp, objv[2])); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method2 : public object_cmd_base -{ - typedef R (C::*mem_type)(T1, T2); - typedef R (C::*cmem_type)(T1, T2) const; - -public: - method2(mem_type f) : f_(f), cmem_(false) {} - method2(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &) - { - check_params_no(objc, 4); - - C *p = static_cast(pv); - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1, _2), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3])); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1, _2), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3])); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method3 : public object_cmd_base -{ - typedef R (C::*mem_type)(T1, T2, T3); - typedef R (C::*cmem_type)(T1, T2, T3) const; - -public: - method3(mem_type f) : f_(f), cmem_(false) {} - method3(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &) - { - check_params_no(objc, 5); - - C *p = static_cast(pv); - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1, _2, _3), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4])); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1, _2, _3), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4])); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method4 : public object_cmd_base -{ - typedef R (C::*mem_type)(T1, T2, T3, T4); - typedef R (C::*cmem_type)(T1, T2, T3, T4) const; - -public: - method4(mem_type f) : f_(f), cmem_(false) {} - method4(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &) - { - check_params_no(objc, 6); - - C *p = static_cast(pv); - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1, _2, _3, _4), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5])); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1, _2, _3, _4), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5])); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method5 : public object_cmd_base -{ - typedef R (C::*mem_type)(T1, T2, T3, T4, T5); - typedef R (C::*cmem_type)(T1, T2, T3, T4, T5) const; - -public: - method5(mem_type f) : f_(f), cmem_(false) {} - method5(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &) - { - check_params_no(objc, 7); - - C *p = static_cast(pv); - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1, _2, _3, _4, _5), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6])); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1, _2, _3, _4, _5), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6])); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method6 : public object_cmd_base -{ - typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6); - typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6) const; - -public: - method6(mem_type f) : f_(f), cmem_(false) {} - method6(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &) - { - check_params_no(objc, 8); - - C *p = static_cast(pv); - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1, _2, _3, _4, _5, _6), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7])); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1, _2, _3, _4, _5, _6), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7])); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method7 : public object_cmd_base -{ - typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6, T7); - typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6, T7) const; - -public: - method7(mem_type f) : f_(f), cmem_(false) {} - method7(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &) - { - check_params_no(objc, 9); - - C *p = static_cast(pv); - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1, _2, _3, _4, _5, _6, _7), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - tcl_cast::from(interp, objv[8])); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1, _2, _3, _4, _5, _6, _7), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - tcl_cast::from(interp, objv[8])); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method8 : public object_cmd_base -{ - typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6, T7, T8); - typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6, T7, T8) const; - -public: - method8(mem_type f) : f_(f), cmem_(false) {} - method8(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &) - { - check_params_no(objc, 10); - - C *p = static_cast(pv); - if (cmem_) - { - dispatch::template do_dispatch< - T1, T2, T3, T4, T5, T6, T7, T8>( - interp, std::bind(cf_, p, - _1, _2, _3, _4, _5, _6, _7, _8), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - tcl_cast::from(interp, objv[8]), - tcl_cast::from(interp, objv[9])); - } - else - { - dispatch::template do_dispatch< - T1, T2, T3, T4, T5, T6, T7, T8>( - interp, std::bind(f_, p, - _1, _2, _3, _4, _5, _6, _7, _8), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - tcl_cast::from(interp, objv[8]), - tcl_cast::from(interp, objv[9])); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method9 : public object_cmd_base -{ - typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6, T7, T8, T9); - typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6, T7, T8, T9) const; - -public: - method9(mem_type f) : f_(f), cmem_(false) {} - method9(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &) - { - check_params_no(objc, 11); - - C *p = static_cast(pv); - if (cmem_) - { - dispatch::template do_dispatch< - T1, T2, T3, T4, T5, T6, T7, T8, T9>( - interp, std::bind(cf_, p, - _1, _2, _3, _4, _5, _6, _7, _8, _9), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - tcl_cast::from(interp, objv[8]), - tcl_cast::from(interp, objv[9]), - tcl_cast::from(interp, objv[10])); - } - else - { - dispatch::template do_dispatch< - T1, T2, T3, T4, T5, T6, T7, T8, T9>( - interp, std::bind(f_, p, - _1, _2, _3, _4, _5, _6, _7, _8, _9), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - tcl_cast::from(interp, objv[8]), - tcl_cast::from(interp, objv[9]), - tcl_cast::from(interp, objv[10])); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; diff --git a/details/methods_v.h b/details/methods_v.h deleted file mode 100644 index 31675bb..0000000 --- a/details/methods_v.h +++ /dev/null @@ -1,451 +0,0 @@ -// -// Copyright (C) 2004-2006, Maciej Sobczak -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// - -// Note: this file is not supposed to be a stand-alone header - - -template -class method1 : public object_cmd_base -{ - typedef object const & T1; - typedef R (C::*mem_type)(T1); - typedef R (C::*cmem_type)(T1) const; - enum { var_start = 2 }; - -public: - method1(mem_type f) : f_(f), cmem_(false) {} - method1(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &pol) - { - C *p = static_cast(pv); - - object t1 = get_var_params(interp, objc, objv, var_start, pol); - - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1), - t1); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1), - t1); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method2 : public object_cmd_base -{ - typedef object const & T2; - typedef R (C::*mem_type)(T1, T2); - typedef R (C::*cmem_type)(T1, T2) const; - enum { var_start = 3 }; - -public: - method2(mem_type f) : f_(f), cmem_(false) {} - method2(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &pol) - { - C *p = static_cast(pv); - - object t2 = get_var_params(interp, objc, objv, var_start, pol); - - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1, _2), - tcl_cast::from(interp, objv[2]), - t2); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1, _2), - tcl_cast::from(interp, objv[2]), - t2); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method3 : public object_cmd_base -{ - typedef object const & T3; - typedef R (C::*mem_type)(T1, T2, T3); - typedef R (C::*cmem_type)(T1, T2, T3) const; - enum { var_start = 4 }; - -public: - method3(mem_type f) : f_(f), cmem_(false) {} - method3(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &pol) - { - C *p = static_cast(pv); - - object t3 = get_var_params(interp, objc, objv, var_start, pol); - - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1, _2, _3), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - t3); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1, _2, _3), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - t3); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method4 : public object_cmd_base -{ - typedef object const & T4; - typedef R (C::*mem_type)(T1, T2, T3, T4); - typedef R (C::*cmem_type)(T1, T2, T3, T4) const; - enum { var_start = 5 }; - -public: - method4(mem_type f) : f_(f), cmem_(false) {} - method4(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &pol) - { - C *p = static_cast(pv); - - object t4 = get_var_params(interp, objc, objv, var_start, pol); - - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1, _2, _3, _4), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - t4); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1, _2, _3, _4), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - t4); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method5 : public object_cmd_base -{ - typedef object const & T5; - typedef R (C::*mem_type)(T1, T2, T3, T4, T5); - typedef R (C::*cmem_type)(T1, T2, T3, T4, T5) const; - enum { var_start = 6 }; - -public: - method5(mem_type f) : f_(f), cmem_(false) {} - method5(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &pol) - { - C *p = static_cast(pv); - - object t5 = get_var_params(interp, objc, objv, var_start, pol); - - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1, _2, _3, _4, _5), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - t5); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1, _2, _3, _4, _5), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - t5); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method6 - : public object_cmd_base -{ - typedef object const & T6; - typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6); - typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6) const; - enum { var_start = 7 }; - -public: - method6(mem_type f) : f_(f), cmem_(false) {} - method6(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &pol) - { - C *p = static_cast(pv); - - object t6 = get_var_params(interp, objc, objv, var_start, pol); - - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1, _2, _3, _4, _5, _6), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - t6); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1, _2, _3, _4, _5, _6), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - t6); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method7 - : public object_cmd_base -{ - typedef object const & T7; - typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6, T7); - typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6, T7) const; - enum { var_start = 8 }; - -public: - method7(mem_type f) : f_(f), cmem_(false) {} - method7(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &pol) - { - C *p = static_cast(pv); - - object t7 = get_var_params(interp, objc, objv, var_start, pol); - - if (cmem_) - { - dispatch::template do_dispatch( - interp, std::bind(cf_, p, _1, _2, _3, _4, _5, _6, _7), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - t7); - } - else - { - dispatch::template do_dispatch( - interp, std::bind(f_, p, _1, _2, _3, _4, _5, _6, _7), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - t7); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method8 - : public object_cmd_base -{ - typedef object const & T8; - typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6, T7, T8); - typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6, T7, T8) const; - enum { var_start = 9 }; - -public: - method8(mem_type f) : f_(f), cmem_(false) {} - method8(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &pol) - { - C *p = static_cast(pv); - - object t8 = get_var_params(interp, objc, objv, var_start, pol); - - if (cmem_) - { - dispatch::template do_dispatch< - T1, T2, T3, T4, T5, T6, T7, T8>( - interp, std::bind(cf_, p, - _1, _2, _3, _4, _5, _6, _7, _8), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - tcl_cast::from(interp, objv[8]), - t8); - } - else - { - dispatch::template do_dispatch< - T1, T2, T3, T4, T5, T6, T7, T8>( - interp, std::bind(f_, p, - _1, _2, _3, _4, _5, _6, _7, _8), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - tcl_cast::from(interp, objv[8]), - t8); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; - -template -class method9 - : public object_cmd_base -{ - typedef object const & T9; - typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6, T7, T8, T9); - typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6, T7, T8, T9) const; - enum { var_start = 10 }; - -public: - method9(mem_type f) : f_(f), cmem_(false) {} - method9(cmem_type f) : cf_(f), cmem_(true) {} - - virtual void invoke(void *pv, Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], policies const &pol) - { - C *p = static_cast(pv); - - object t9 = get_var_params(interp, objc, objv, var_start, pol); - - if (cmem_) - { - dispatch::template do_dispatch< - T1, T2, T3, T4, T5, T6, T7, T8, T9>( - interp, std::bind(cf_, p, - _1, _2, _3, _4, _5, _6, _7, _8, _9), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - tcl_cast::from(interp, objv[8]), - tcl_cast::from(interp, objv[9]), - t9); - } - else - { - dispatch::template do_dispatch< - T1, T2, T3, T4, T5, T6, T7, T8, T9>( - interp, std::bind(f_, p, - _1, _2, _3, _4, _5, _6, _7, _8, _9), - tcl_cast::from(interp, objv[2]), - tcl_cast::from(interp, objv[3]), - tcl_cast::from(interp, objv[4]), - tcl_cast::from(interp, objv[5]), - tcl_cast::from(interp, objv[6]), - tcl_cast::from(interp, objv[7]), - tcl_cast::from(interp, objv[8]), - tcl_cast::from(interp, objv[9]), - t9); - } - } - -private: - mem_type f_; - cmem_type cf_; - bool cmem_; -}; diff --git a/game.h b/game.h deleted file mode 100644 index c0b92f2..0000000 --- a/game.h +++ /dev/null @@ -1,409 +0,0 @@ -#ifndef GAME_H -#define GAME_H - -#include -#include -#include -#include -#include - -#include "reversi.h" -#include "tree.h" - -using namespace std; - -enum player_type{ - ply_human,ply_ai,ply_other -}; -struct player{ - player_type p_type; - string path; -}; - -class game{ -public: - game(): brd{0,0}, color(true), pos{-1,-1}, - mthd(method(mthd_ab | mthd_kill | mthd_pvs | mthd_trans | mthd_mtdf | mthd_ptn)), - depth(-1), flag_auto_save(true), flag_lock(true), - ply_white{ply_ai,"Irius offline"},ply_black{ply_human,"Irius offline"} {} - virtual ~game(){} - - board brd; - bool color; - coordinate pos; - method mthd; - short depth; - - bool flag_auto_save; - bool flag_lock; - - player ply_white, ply_black; - - player& get_ply(bool color){ - return *(&ply_white + color); - } - const player& get_ply(bool color)const{ - return *(&ply_white + color); - } - - struct pack{ - board brd; - bool color; - coordinate pos; - }; - vector record; - vector storage; - - virtual void show(){ - brd.print(cout); - } - virtual void print_log(const string& str){ - cout << str; - } - - void set_color(cbool _color){ - push(); - color = _color; - show(); - } - void set_pos(cpos_type x,cpos_type y){ - push(); - pos = {x,y}; - show(); - } - void start(){ - color = true; - pos = {-1,-1}; - record.clear(); - brd.initial(); - print_log("start a new game\n"); - flag_lock = false; - show(); - play(); - } - - bool undo(){ - bool result = pop(); - if(result){ - print_log("undo\n"); - flag_lock = false; - show(); - } - return result; - } - bool redo(){ - if(storage.empty()){ - return false; - }else{ - pack temp = {brd,color,pos}; - record.push_back(temp); - - temp = storage.back(); - storage.pop_back(); - brd = temp.brd; - color = temp.color; - pos = temp.pos; - - print_log("redo\n"); - flag_lock = false; - - show(); - return true; - } - } - brd_type bget(cbool color){ - return brd.bget(color); - } - void assign(cbrd_type _brd_black,cbrd_type _brd_white){ - push(); - brd.assign(_brd_black,_brd_white); - show(); - print_log("assign new value to the board\n"); - } - void assign(cboard _brd){ - push(); - brd = _brd; - show(); - print_log("assign new value to the board\n"); - } - - chessman get(cpos_type x,cpos_type y){ - return brd.get(x + (y << 3)); - } - void set(cpos_type x, cpos_type y, cchessman chsman){ - push(); - brd.set(x + (y << 3),chsman); - show(); - } - void mirror_h(){ - push(); - brd.mirror_h(); - pos.x = board::size - pos.x - 1; - print_log("mirror horizontally\n"); - show(); - } - void mirror_v(){ - push(); - brd.mirror_v(); - pos.y = board::size - pos.y - 1; - print_log("mirror vertically\n"); - show(); - } - void rotate_l(){ - push(); - brd.rotate_l(); - swap(pos.x,pos.y); - pos.y = 7 - pos.y; - print_log("rotate clockwise\n"); - show(); - } - void rotate_r(){ - push(); - brd.rotate_r(); - swap(pos.x,pos.y); - pos.x = 7 - pos.x; - print_log("rotate counterclockwise\n"); - show(); - } - void reflect(){ - push(); - brd.reflect(); - pos.x = board::size - pos.x - 1; - pos.y = board::size - pos.y - 1; - print_log("reflect\n"); - show(); - } - void reverse(){ - push(); - brd.reverse(); - color = !color; - print_log("reverse\n"); - show(); - } - void config(){ - return brd.config(); - } - bool flip(cbool color, cpos_type x, cpos_type y){ - push(); - bool result; - if(x < 0 || x >= board::size || y < 0 || y >= board::size){ - result = false; - }else{ - board brd_save = brd; - brd.flip(color,x + (y << 3)); - result = (brd != brd_save); - } - if(result){ - print_log( - string("place a ") + (color ? "black" : "white") - + " stone at " + char(x + 'A') + char(y + '1') + "\n" - ); - if(!(brd.get_status(!color) & sts_again)){ - this->color = !color; - } - this->pos = coordinate(x,y); - show(); - }else{ - if(flag_auto_save){ - pop(); - } - print_log( - string("cannot place a ") + (color ? "black" : "white") - +" stone here\n" - ); - } - return result; - } - - int count(cbool color){ - return brd.count(color); - } - brd_type get_move(cbool color){ - return brd.get_move(color); - } - int count_move(cbool color){ - return brd.count_move(color); - } - float score(cbool color){ - return brd.score(color); - } -// float score_ptn(cbool color){ -// return brd.score_ptn(color); -// } - pair process_method(cmethod mthd,cshort depth){ - pair result = {mthd,depth}; - short total = this->brd.sum(); - - if(result.first == mthd_rnd){ - return result; - } - - if(result.second == -1){ - if(total <= 7){ - result.second = 9; - }else if(total <= 10){ - result.second = 8; - }else if(total <= board::size2 - 22){ - result.second = 7; - }else if(total <= board::size2 - 15){ - result.second = 8; - }else{ - result.second = 20; - } - } - if(result.second == -2){ - if(total <= 7){ - result.second = 9; - }else if(total <= 10){ - result.second = 9; - }else if(total <= board::size2 - 24){ - result.second = 8; - }else if(total <= board::size2 - 16){ - result.second = 9; - }else{ - result.second = 20; - } - } - if(result.second <= -3){ - if(total <= 7){ - result.second = 11; - }else if(total <= 10){ - result.second = 10; - }else if(total <= board::size2 - 22){ - result.second = 10; - }else if(total <= board::size2 - 16){ - result.second = 10; - }else{ - result.second = 20; - } - } - if(result.second >= board::size2 - total - 1){ - result.first = method(mthd | mthd_end); - result.second = board::size2 - total - 1; - } - return result; - } - calc_type search(cmethod mthd,cbool color,cshort depth = -1, - ccalc_type alpha = _inf,ccalc_type beta = inf){ - pair p_mthd = process_method(mthd,depth); - return brd.search(p_mthd.first,color,p_mthd.second,alpha,beta); - } - virtual vector get_choice(cmethod mthd,cbool color,cshort depth = -1){ - pair p_mthd = process_method(mthd,depth); - return brd.get_choice(p_mthd.first,color,p_mthd.second); - } - choice select_choice(const vector& choices){ - return brd.select_choice(choices); - } - coordinate play_ai(cmethod mthd,cbool color,cshort depth = -1){ - push(); - pair p_mthd = process_method(mthd,depth); - auto pos = brd.play(p_mthd.first,color,p_mthd.second); - if(pos.x >= 0){ - print_log( - string("place a ") + (color ? "black" : "white") - + " stone at " + char(pos.x + 'A') + char(pos.y + '1') + "\n" - ); - if(!(brd.get_status(!color) & sts_again)){ - this->color = !color; - } - this->pos = pos; - show(); - }else{ - print_log( - string(color? ("black") : ("white")) - + " is unable to move.\n" - ); - if(flag_auto_save){ - pop(); - } - } - return pos; - } - virtual coordinate play_other(cmethod mthd,cbool color,cshort depth = -1){ - return coordinate(-1,-1); - } - coordinate play(cmethod mthd,cbool color,cshort depth = -1){ - switch(get_ply(color).p_type){ - case ply_human: - return coordinate(-1,-1); - case ply_ai: - return play_ai(mthd,color,depth); - case ply_other: - return play_other(mthd,color,depth); - default: - return coordinate(-1,-1); - } - } - coordinate play(){ - sts_type status; - - while((status = brd.get_status(color)) & sts_turn){ - if(get_ply(color).p_type == ply_human){ - return coordinate(-1,-1); - } - - play(mthd,color,depth); - } - - flag_lock = true; - string str = to_string(brd.count(true)) - + " black stones and " - + to_string(brd.count(false)) - + " white stones remain\n"; - if(status == sts_bwin){ - str += "black wins\n"; - }else if(status == sts_wwin){ - str += "white wins\n"; - }else{ - str += "a tie\n"; - } - print_log(str); - - return coordinate(-1,-1); - } - - coordinate play(ccoordinate pos){ - sts_type status = brd.get_status(color); - - if(!(status & sts_turn)){ - return coordinate(-1,-1); - } - - if(get_ply(color).p_type == ply_human){ - flip(color,pos.x,pos.y); - } - play(mthd,color,depth); - - play(); - return coordinate(-1,-1); - } - -protected: - void push(){ - if(flag_auto_save){ - pack temp = {brd,color,pos}; - record.push_back(temp); - storage.clear(); - } - } - - bool pop(){ - if(record.empty()){ - return false; - }else{ - pack temp = {brd,color,pos}; - storage.push_back(temp); - - temp = record.back(); - record.pop_back(); - brd = temp.brd; - color = temp.color; - pos = temp.pos; - - return true; - } - } -}; - -#endif //GAME_H diff --git a/image/reversi.png b/image/reversi.png index 7cb5579..d9e4aa4 100644 Binary files a/image/reversi.png and b/image/reversi.png differ diff --git a/jsoncpp/json-forwards.h b/jsoncpp/json-forwards.h deleted file mode 100644 index fd21c05..0000000 --- a/jsoncpp/json-forwards.h +++ /dev/null @@ -1,264 +0,0 @@ -/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/). -/// It is intented to be used with #include -/// This header provides forward declaration for all JsonCpp types. - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is -released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur - -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. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - -#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED -# define JSON_FORWARD_AMALGATED_H_INCLUDED -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -#define JSON_IS_AMALGAMATION - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_CONFIG_H_INCLUDED -#define JSON_CONFIG_H_INCLUDED - -/// If defined, indicates that json library is embedded in CppTL library. -//# define JSON_IN_CPPTL 1 - -/// If defined, indicates that json may leverage CppTL library -//# define JSON_USE_CPPTL 1 -/// If defined, indicates that cpptl vector based map should be used instead of -/// std::map -/// as Value container. -//# define JSON_USE_CPPTL_SMALLMAP 1 -/// If defined, indicates that Json specific container should be used -/// (hash table & simple deque container with customizable allocator). -/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 -//# define JSON_VALUE_USE_INTERNAL_MAP 1 -/// Force usage of standard new/malloc based allocator instead of memory pool -/// based allocator. -/// The memory pools allocator used optimization (initializing Value and -/// ValueInternalLink -/// as if it was a POD) that may cause some validation tool to report errors. -/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. -//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 - -// If non-zero, the library uses exceptions to report bad input instead of C -// assertion macros. The default is to use exceptions. -#ifndef JSON_USE_EXCEPTION -#define JSON_USE_EXCEPTION 1 -#endif - -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgated header. -// #define JSON_IS_AMALGAMATION - -#ifdef JSON_IN_CPPTL -#include -#ifndef JSON_USE_CPPTL -#define JSON_USE_CPPTL 1 -#endif -#endif - -#ifdef JSON_IN_CPPTL -#define JSON_API CPPTL_API -#elif defined(JSON_DLL_BUILD) -#if defined(_MSC_VER) -#define JSON_API __declspec(dllexport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#endif // if defined(_MSC_VER) -#elif defined(JSON_DLL) -#if defined(_MSC_VER) -#define JSON_API __declspec(dllimport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#endif // if defined(_MSC_VER) -#endif // ifdef JSON_IN_CPPTL -#if !defined(JSON_API) -#define JSON_API -#endif - -// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for -// integer -// Storages, and 64 bits integer support is disabled. -// #define JSON_NO_INT64 1 - -#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 -// Microsoft Visual Studio 6 only support conversion from __int64 to double -// (no conversion from unsigned __int64). -#define JSON_USE_INT64_DOUBLE_CONVERSION 1 -// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' -// characters in the debug information) -// All projects I've ever seen with VS6 were using this globally (not bothering -// with pragma push/pop). -#pragma warning(disable : 4786) -#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 - -#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 -/// Indicates that the following function is deprecated. -#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) -#endif - -#if !defined(JSONCPP_DEPRECATED) -#define JSONCPP_DEPRECATED(message) -#endif // if !defined(JSONCPP_DEPRECATED) - -namespace Json { -typedef int Int; -typedef unsigned int UInt; -#if defined(JSON_NO_INT64) -typedef int LargestInt; -typedef unsigned int LargestUInt; -#undef JSON_HAS_INT64 -#else // if defined(JSON_NO_INT64) -// For Microsoft Visual use specific types as long long is not supported -#if defined(_MSC_VER) // Microsoft Visual Studio -typedef __int64 Int64; -typedef unsigned __int64 UInt64; -#else // if defined(_MSC_VER) // Other platforms, use long long -typedef long long int Int64; -typedef unsigned long long int UInt64; -#endif // if defined(_MSC_VER) -typedef Int64 LargestInt; -typedef UInt64 LargestUInt; -#define JSON_HAS_INT64 -#endif // if defined(JSON_NO_INT64) -} // end namespace Json - -#endif // JSON_CONFIG_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_FORWARDS_H_INCLUDED -#define JSON_FORWARDS_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -// writer.h -class FastWriter; -class StyledWriter; - -// reader.h -class Reader; - -// features.h -class Features; - -// value.h -typedef unsigned int ArrayIndex; -class StaticString; -class Path; -class PathArgument; -class Value; -class ValueIteratorBase; -class ValueIterator; -class ValueConstIterator; -#ifdef JSON_VALUE_USE_INTERNAL_MAP -class ValueMapAllocator; -class ValueInternalLink; -class ValueInternalArray; -class ValueInternalMap; -#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - -} // namespace Json - -#endif // JSON_FORWARDS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - - - - - -#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED diff --git a/main.cc b/main.cc deleted file mode 100644 index 8e33c03..0000000 --- a/main.cc +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include -#include - -#include "reversi_tcl.h" - -using namespace std; - -#ifdef DEBUG_SEARCH - ofstream out; -#endif - -bool flag_quit = false; - -void quit(){ - #ifdef DEBUG_SEARCH - out.close(); - #endif - flag_quit = true; -} - -void game_gui::show(){ - brd.print(); -} - -void print_term(const string& str){ - cout << str << endl; -} -void print_log(const string& str){} -void print_status(const string& str){} -void show_choice(const vector& choices){} -void load_book(const string& path){} - -int main(){ - - #ifdef DEBUG_SEARCH - out.open("out.html"); - #endif - - board::flag_unicode = false; - - string str,s; - string::size_type pos; - while(cout << ">>", getline(cin,str)){ - pos = str.find_last_not_of(" \n\t"); - if(pos != str.npos){ - if(str[pos] == '\\'){ - while(getline(cin,s)){ - pos = s.find_last_not_of(" \n\t"); - if(pos == s.npos){ - break; - } - if(s[pos] != '\\'){ - break; - } - str += '\n'; - str += s; - } - if(!cin){ - break; - } - str += '\n'; - str += s; - } - } - process(str); - if(flag_quit) - break; - } - - #ifdef DEBUG_SEARCH - out.close(); - #endif - - return 0; -} diff --git a/optimize/makefile b/optimize/makefile deleted file mode 100644 index 98f0550..0000000 --- a/optimize/makefile +++ /dev/null @@ -1,27 +0,0 @@ -.PHONY: all clean clean_all - -all: test.png - -clean_all: clean - rm gmon.out - -clean: - rm prof.log test.dot rtest.dot test.png - -test.exe: ../bin/Debug/reversi_json.exe - cp ../bin/Debug/reversi_json.exe ./test.exe - -gmon.out: test.exe in.txt - cat in.txt | ./test.exe - -prof.log: test.exe gmon.out - gprof test.exe gmon.out > prof.log - -test.dot: prof.log - gprof2dot prof.log > test.dot - -rtest.dot: test.dot - python replace.py test.dot rtest.dot - -test.png: rtest.dot - dot -Tpng -otest.png rtest.dot \ No newline at end of file diff --git a/optimize/test.exe b/optimize/test.exe deleted file mode 100644 index d6f1c62..0000000 Binary files a/optimize/test.exe and /dev/null differ diff --git a/profile/data b/profile/data new file mode 120000 index 0000000..4909e06 --- /dev/null +++ b/profile/data @@ -0,0 +1 @@ +../data \ No newline at end of file diff --git a/optimize/in.txt b/profile/in.txt similarity index 100% rename from optimize/in.txt rename to profile/in.txt diff --git a/profile/jsoncpp b/profile/jsoncpp new file mode 120000 index 0000000..fa99cd4 --- /dev/null +++ b/profile/jsoncpp @@ -0,0 +1 @@ +../cpp/jsoncpp \ No newline at end of file diff --git a/profile/jsoncpp.cpp b/profile/jsoncpp.cpp new file mode 120000 index 0000000..9d8c4e6 --- /dev/null +++ b/profile/jsoncpp.cpp @@ -0,0 +1 @@ +../cpp/jsoncpp.cpp \ No newline at end of file diff --git a/profile/main.cc b/profile/main.cc new file mode 100644 index 0000000..0621857 --- /dev/null +++ b/profile/main.cc @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +#include "jsoncpp/json.h" + +#include "../cpp/reversi.h" +#include "../cpp/pattern.h" + +using namespace std; + +int main(int argc, char *argv[], char *envp[]){ + int x,y; + bool mycolor; + + board brd; + board::config(); + pattern::config(); + brd.initial(); + + // input JSON + string str; + getline(cin, str); + Json::Reader reader; + Json::Value input,result; + Json::FastWriter writer; + reader.parse(str, input); + + // 分析自己收到的输入和自己过往的输出,并恢复状态 + int turns = input["responses"].size(); + mycolor = (input["requests"][(Json::Value::UInt) 0]["x"].asInt() < 0); + + for (int i = 0; i < turns; i++) + { + // 根据这些输入输出逐渐恢复状态到当前回合 + x = input["requests"][i]["x"].asInt(); + y = input["requests"][i]["y"].asInt(); + if (x >= 0) + brd.flip(!mycolor,x + (y << 3)); // 模拟对方落子 + + x = input["responses"][i]["x"].asInt(); + y = input["responses"][i]["y"].asInt(); + if (x >= 0) + brd.flip(mycolor,x + (y << 3)); // 模拟己方落子 + } + + // 看看自己本回合输入 + x = input["requests"][turns]["x"].asInt(); + y = input["requests"][turns]["y"].asInt(); + + if (x >= 0) + brd.flip(!mycolor,x + (y << 3)); // 模拟对方落子 + + grp.load("./data/pattern2.dat"); + + method mthd = method(mthd_ab | mthd_pvs | mthd_kill | mthd_mtdf | mthd_ptn | mthd_trans); + short depth = -2; + auto p_mthd = brd.process_method(mthd, depth); + mthd = p_mthd.first; + depth = p_mthd.second; + auto coord = brd.play(mthd, mycolor, depth); + + // 决策结束,输出结果(你只需修改以上部分) + + result["response"]["x"] = coord.x; + result["response"]["y"] = coord.y; + cout << writer.write(result) << endl; + + return 0; +} diff --git a/profile/makefile b/profile/makefile new file mode 100644 index 0000000..75df3f7 --- /dev/null +++ b/profile/makefile @@ -0,0 +1,70 @@ +WORKDIR = `pwd` + +CC = gcc +CXX = g++ +AR = ar +LD = g++ +WINDRES = windres +RM = rm -f + +INC = +CFLAGS = +CXXFLAGS = -Wall -pg -std=c++11 -fno-omit-frame-pointer -O2 +RESINC = +LIBDIR = +LIB = +LDFLAGS = -pg + +SRCDIR = ../cpp/ +OBJDIR = obj/ +OUTDIR = ./ + +SRC = $(wildcard $(SRCDIR)*.cc) main.cc +OBJ = $(patsubst %.cc, %.o, $(patsubst $(SRCDIR)%, $(OBJDIR)%, $(SRC))) +OUT = $(OUTDIR)reversi + +.PHONY: all clean before + +all: test.png + +clean: + -$(RM) $(OBJDIR)*.o + -$(RM) $(addprefix $(OUTDIR), *.o *.exe *.dll *.so *.pyd *.log *.dot *.png *.out) $(OUT) + +test.png: test_replace.dot + dot -Tpng -o$@ $< + +test_replace.dot: test.dot + python replace.py $< $@ + +test.dot: prof.log + gprof2dot $< > $@ + +prof.log: $(OUT) gmon.out + gprof $(OUT) gmon.out > $@ + +gmon.out: $(OUT) in.txt + cat in.txt | $(OUT) + +before: + test -d $(OBJDIR) || mkdir -p $(OBJDIR) + test -d $(OUTDIR) || mkdir -p $(OUTDIR) + +$(OUT): before $(OBJ) + $(LD) $(LDFLAGS) $(LIBDIR) $(OBJ) -o $@ + +$(OBJDIR)reversi.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM $(SRCDIR)reversi.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(OBJDIR)flip.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM $(SRCDIR)flip.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(OBJDIR)search.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM $(SRCDIR)search.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(OBJDIR)pattern.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM $(SRCDIR)pattern.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +main.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM main.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ + diff --git a/profile/parse.awk b/profile/parse.awk new file mode 100644 index 0000000..19881cf --- /dev/null +++ b/profile/parse.awk @@ -0,0 +1,9 @@ +BEGIN {} +{ + for (i = 1; i <= NF; ++i) { + if($i != "\\"){ + printf "%s ", $i + } + } +} +END {printf "\n"} diff --git a/optimize/replace.py b/profile/replace.py similarity index 95% rename from optimize/replace.py rename to profile/replace.py index 2a6e3c9..d75c97e 100644 --- a/optimize/replace.py +++ b/profile/replace.py @@ -1,24 +1,24 @@ -import sys; -import re; -import os; - -if len(sys.argv) < 3: - exit(1); - -filename = sys.argv[1]; -if not os.path.isfile(filename): - exit(1); - -fobj = open(filename); -lines = fobj.readlines(); -fobj.close(); - -for i in range(0,len(lines)): - lines[i] = re.sub(r"\\n([0-9]*)[^0-9]{2}\"",r'\\n\g<1>"',lines[i]); - lines[i] = re.sub(r"label=\"([0-9]*)[^0-9]{2}\"",r'label="\g<1>"',lines[i]); - -filename = sys.argv[2]; - -fobj = open(filename,"w"); -lines = fobj.writelines(lines); +import sys; +import re; +import os; + +if len(sys.argv) < 3: + exit(1); + +filename = sys.argv[1]; +if not os.path.isfile(filename): + exit(1); + +fobj = open(filename); +lines = fobj.readlines(); +fobj.close(); + +for i in range(0,len(lines)): + lines[i] = re.sub(r"\\n([0-9]*)[^0-9]{2}\"",r'\\n\g<1>"',lines[i]); + lines[i] = re.sub(r"label=\"([0-9]*)[^0-9]{2}\"",r'label="\g<1>"',lines[i]); + +filename = sys.argv[2]; + +fobj = open(filename,"w"); +lines = fobj.writelines(lines); fobj.close(); \ No newline at end of file diff --git a/python/game.py b/python/game.py new file mode 100644 index 0000000..67d51a5 --- /dev/null +++ b/python/game.py @@ -0,0 +1,525 @@ +# -*- coding: utf-8 -*- + +import wx; +import reversi; +import reversi as rv; +import json; +import subprocess as sp; +from enum import Enum; + +bias = 34; +num = 8; +cell = 44; +width = num * cell; +cbias = bias + cell / 2; +radius = cell / 2 - 4; +thick = 3; +margin = 20; + +def check(pos): + return pos[0] >= 0 and pos[0] < rv.board.size and pos[1] >= 0 and pos[1] < rv.board.size; + +def coord2str(self): + return "(%d,%d)" % (self.x,self.y); +setattr(reversi.coordinate,"__str__",coord2str); + +def choice2str(self): + return "(%d,%d,%f)" % (self.pos & 7,self.pos >> 3,self.val); +setattr(reversi.choice,"__str__",choice2str); + +def choices2str(self): + return "[" + ",".join([choice2str(c) for c in self]) + "]"; +setattr(reversi.choices,"__str__",choices2str); + +def floats2str(self): + return "[" + ",".join([str(f) for f in self]) + "]"; +setattr(reversi.floats,"__str__",floats2str) + +class player: + pass; + +class game: + brd = rv.board(0, 0); + color = True; + pos = (-1, -1); + mthd = rv.mthd_ab | rv.mthd_kill | rv.mthd_pvs | rv.mthd_trans | rv.mthd_mtdf | rv.mthd_ptn; + depth = -1; + flag_auto_save = True; + flag_lock = True; + ply = (player(), player()); + record = []; + storage = []; + choices = None; + + def __init__(self): + self.ply[False].type = rv.ply_ai; + self.ply[False].path = "bot/Irius" + self.ply[True].type = rv.ply_human; + self.ply[True].path = "bot/Irius" + + def show(self): + self.do_show(self.dc); + + def do_show(self, dc): + dc.Clear(); + + #draw valid moves + dc.SetBrush(wx.Brush(wx.Colour(30,100,0))); + dc.SetPen(wx.Pen(wx.Colour(30,100,0), thick)); + brd_move = self.brd.get_move(self.color); + for i in range(reversi.board.size2): + if brd_move & (1 << i): + dc.DrawRectangle(bias + cell * (i & 7), bias + cell * (i >> 3), cell, cell); + + #draw a board + dc.SetPen(wx.Pen(wx.BLACK, thick)); + for i in range(num + 1): + dc.DrawLine(bias, bias + cell * i, bias + width, bias + cell * i); + for i in range(num + 1): + dc.DrawLine(bias + cell * i, bias, bias + cell * i, bias + width); + + #draw the outline of the board + dc.SetBrush(wx.BLACK_BRUSH); + dc.SetPen(wx.Pen(wx.BLACK,thick)); + dc.DrawRectangle(bias - margin, bias - margin, margin, width + margin * 2); + dc.DrawRectangle(bias - margin, bias - margin, width + margin * 2, margin); + dc.DrawRectangle(bias + width, bias - margin, margin, width + margin * 2); + dc.DrawRectangle(bias - margin, bias + width, width + margin * 2, margin); + + #draw coordinate labels + dc.SetTextForeground(wx.Colour(190,190,190)); + dc.SetFont( + wx.Font( + 12, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_BOLD,False, "Consolas" + ,wx.FONTENCODING_DEFAULT + ) + ); + for i in range(num): + dc.DrawText(chr(ord('A') + i), bias + cell / 2 + cell * i - 4, bias - margin / 2 - 10); + dc.DrawText(chr(ord('A') + i), bias + cell / 2 + cell * i - 4, bias + width + margin / 2 - 12); + dc.DrawText(chr(ord('1') + i), bias - margin / 2 - 4,bias + cell / 2 + cell * i - 10); + dc.DrawText(chr(ord('1') + i), bias + width + margin / 2 - 5, bias + cell / 2 + cell * i - 10); + + #draw stones + for i in range(num): + for j in range(num): + chssmn = self.brd.get(i + (j << 3)); + if chssmn == rv.black: + dc.SetBrush(wx.Brush(wx.Colour(40,40,40))); + dc.SetPen(wx.Pen(wx.Colour(20,20,20), thick)); + dc.DrawCircle(wx.Point(cbias + cell * i, cbias + cell * j),radius); + + elif chssmn == reversi.white: + dc.SetBrush(wx.Brush(wx.Colour(210,210,210))); + dc.SetPen(wx.Pen(wx.Colour(230,230,230), thick)); + dc.DrawCircle(wx.Point(cbias + cell * i, cbias + cell * j),radius); + + #show where is the last move + if check(self.pos): + if self.get(self.pos[0], self.pos[1]) == rv.black: + dc.SetBrush(wx.Brush(wx.Colour(50,50,30))); + dc.SetPen(wx.Pen(wx.Colour(90,90,0), thick)); + else: + dc.SetBrush(wx.Brush(wx.Colour(210,210,170))); + dc.SetPen(wx.Pen(wx.Colour(200,200,30), thick)); + dc.DrawCircle(wx.Point(cbias + cell * self.pos[0], cbias + cell * self.pos[1]),radius); + + if not (self.choices is None): + dc.SetTextForeground(wx.Colour(255,30,30)); + dc.SetFont( + wx.Font( + 9, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_BOLD, False, "Consolas", + wx.FONTENCODING_DEFAULT + ) + ); + for c in self.choices: + x = c.pos & 7; + y = c.pos >> 3; + s = "%.3f" % c.val; + dc.DrawText( + s, + bias + cell * x + cell / 2 - 3.5 * len(s), + bias + cell * y + cell / 2 - 8 + ); + + def paint(self, show_choice = False): + if not show_choice: + self.choices = None; + evt = wx.PaintEvent(self.panel_board.GetId()); + self.panel_board.GetEventHandler().ProcessEvent(evt); + + def print_log(self, s): + self.text_log.AppendText(s); + + def export(self, path, img_type = wx.BITMAP_TYPE_PNG): + img = wx.Bitmap(424,424); + memdc = wx.MemoryDC(); + memdc.SelectObject(img); + memdc.SetBackground(wx.Brush(wx.Colour(43,155,0))); + self.do_show(memdc); + img.SaveFile(path, img_type); + + def push(self): + if self.flag_auto_save: + self.record.append((rv.board(self.brd), self.color, self.pos)); + self.storage = []; + + def pop(self): + if len(self.record) == 0: + return False; + else: + self.storage.append((rv.board(self.brd), self.color, self.pos)); + (self.brd, self.color, self.pos) = self.record[-1]; + self.record.pop(); + return True; + + def undo(self): + result = self.pop(); + if result: + self.print_log("undo\n"); + self.flag_lock = False; + self.paint(); + return result; + + def redo(self): + if len(self.storage) == 0: + return False; + else: + self.record.append((rv.board(self.brd), self.color, self.pos)); + (self.brd, self.color, self.pos) = self.storage[-1]; + self.storage.pop(); + self.print_log("redo\n"); + self.flag_lock = False; + self.paint(); + return True; + + def set_color(self, color): + self.push(); + self.color = color; + self.paint(); + + def set_pos(self, x, y): + self.push(); + self.pos = (x, y); + self.paint(); + + def start(self): + self.color = True; + self.pos = (-1,-1); + self.record = []; + self.storage = []; + self.brd.initial(); + self.print_log("start a new game\n"); + self.flag_lock = False; + self.paint(); + self.play_continue(); + + def bget(self, color): + return brd.bget(color); + + def assign(self, brd): + self.push(); + self.brd = brd; + self.paint(); + self.print_log("assign new value to the board\n"); + + def get(self, x, y): + return self.brd.get(x + (y << 3)); + + def set(self, x, y, chsman): + self.push(); + self.brd.set(x + (y << 3), chsman); + self.paint(); + + def mirror_h(self): + self.push(); + self.brd.mirror_h(); + self.pos = (7 - self.pos[0], self.pos[1]); + self.print_log("mirror horizontally\n"); + self.paint(); + + def mirror_v(self): + self.push(); + self.brd.mirror_v(); + self.pos = (self.pos[0], 7 - self.pos[1]); + self.print_log("mirror vertically\n"); + self.paint(); + + def rotate_l(self): + self.push(); + self.brd.rotate_l(); + self.pos = (self.pos[1], 7 - self.pos[0]); + self.print_log("rotate clockwise\n"); + self.paint(); + + def rotate_r(self): + self.push(); + self.brd.rotate_r(); + self.pos = (7 - self.pos[1], self.pos[0]); + self.print_log("rotate counterclockwise\n"); + self.paint(); + + def reflect(self): + self.push(); + self.brd.reflect(); + self.pos = (7 - self.pos[0], 7 - self.pos[1]); + self.print_log("reflect\n"); + self.paint(); + + def reverse(self): + self.push(); + self.brd.reverse(); + self.color = not color; + self.print_log("reverse\n"); + self.paint(); + + def config(self): + return brd.config(); + + def flip(self, color, x, y): + + self.push(); + + result = False; + + # if the BMI2 instruction set is used by the function board::flip() + # we do not need to compare self.brd.get(x + (y << 3)) with rv.blank + if not check((x,y)) or self.brd.get(x + (y << 3)) != rv.blank: + result = False; + else: + brd_save = rv.board(self.brd); + self.brd.flip(color, x + (y << 3)); + result = (self.brd.bget(True) != brd_save.bget(True)); + + if result: + self.print_log( + "place a " + ("black" if color else "white") + + " stone at " + chr(x + ord("A")) + chr(y + ord("1")) + "\n" + ); + if not (self.brd.get_status(not color) & rv.sts_again): + self.color = not color; + self.pos = (x,y); + self.paint(); + else: + if self.flag_auto_save: + self.pop(); + self.print_log( + "cannot place a " + ("black" if color else "white") + +" stone here\n" + ); + return result; + + def count(self, color): + return self.brd.count(color); + + def get_move(self, color): + return self.brd.get_move(color); + + def count_move(self, color): + return self.brd.count_move(color); + + def score(self, color): + return self.brd.score(color); + + def process_method(self, mthd, depth): + result = [mthd, depth]; + total = self.brd.sum(); + + if result[0] == rv.mthd_rnd: + return result; + + if result[1] == -1: + if total <= 7: + result[1] = 10; + elif total <= 10: + result[1] = 9; + elif total <= rv.board.size2 - 22: + result[1] = 8; + elif total <= rv.board.size2 - 15: + result[1] = 9; + else: + result[1] = 20; + elif result[1] == -2: + if total <= 7: + result[1] = 10; + elif total <= 10: + result[1] = 10; + elif total <= rv.board.size2 - 24: + result[1] = 9; + elif total <= rv.board.size2 - 16: + result[1] = 10; + else: + result[1] = 20; + elif result[1] <= -3: + if total <= 7: + result[1] = 11; + elif total <= 10: + result[1] = 11; + elif total <= rv.board.size2 - 24: + result[1] = 10; + elif total <= rv.board.size2 - 16: + result[1] = 11; + else: + result[1] = 20; + if result[1] >= rv.board.size2 - total: + result[0] |= rv.mthd_end; + result[1] = rv.board.size2 - total; + + return result; + + def search(mthd, color, depth = -1, alpha = rv._inf, beta = rv.inf): + (mthd, depth) = process_method(mthd, depth); + return self.brd.search(mthd, color, depth, alpha, beta); + + def get_choice(self, mthd, color, depth = -1): + (mthd, depth) = self.process_method(mthd, depth); + choices = self.brd.get_choice(mthd, color, depth); + self.choices = rv.choices(choices); + self.paint(show_choice = True); + return choices; + + def select_choice(self, choices): + return self.brd.select_choice(choices); + + def play_ai(self, mthd = None, color = None, depth = None): + + if mthd is None: + mthd = self.mthd; + if color is None: + color = self.color; + if depth is None: + depth = self.depth; + + self.push(); + (mthd, depth) = self.process_method(mthd, depth); + pos = self.brd.play(mthd, color, depth); + pos = (pos.x, pos.y); + if pos[0] >= 0: + self.print_log( + "place a " + ("black" if color else "white") + + " stone at " + chr(pos[0] + ord("A")) + chr(pos[1] + ord("1")) + "\n" + ); + if not (self.brd.get_status(not color) & rv.sts_again): + self.color = not color; + self.pos = pos; + self.paint(); + else: + self.print_log( + ("black" if color else "white") + + " is unable to move.\n" + ); + if self.flag_auto_save: + self.pop(); + + return pos; + + def play_other(self, mthd = None, color = None, depth = None): + + if mthd is None: + mthd = self.mthd; + if color is None: + color = self.color; + if depth is None: + depth = self.depth; + + p = sp.Popen(self.ply[color].path, stdin = sp.PIPE, stdout = sp.PIPE); + + result = rv.coordinate(); + request = { + "request":{ + "color":color, + "board":{ + "black":self.brd.bget(True), + "white":self.brd.bget(False) + } + } + }; + + s = json.dumps(request); + + self.text_log.AppendText( + "send a request to process \"" + + self.ply[color].path + + "\"\n" + ); + + self.text_log.AppendText(s + "\n"); + [s, str_err] = p.communicate(s.encode()); + self.text_log.AppendText( + "receive a response from process \"" + + self.ply[color].path + + "\"\n" + ); + + self.text_log.AppendText(s.decode()); + response = json.loads(s.decode()); + + result.x = response["response"]["x"]; + result.y = response["response"]["y"]; + + self.flip(color, result.x, result.y); + + def play(self, mthd = None, color = None, depth = None): + + if mthd is None: + mthd = self.mthd; + if color is None: + color = self.color; + if depth is None: + depth = self.depth; + + p_type = self.ply[color].type; + if p_type == rv.ply_ai: + self.play_ai(mthd, color, depth); + elif p_type == rv.ply_other: + self.play_other(mthd, color, depth); + + def play_continue(self, mthd = None, depth = None): + + if mthd is None: + mthd = self.mthd; + if depth is None: + depth = self.depth; + + status = None; + + while True: + status = self.brd.get_status(self.color); + if not (status & rv.sts_turn): + break; + if self.ply[self.color].type == rv.ply_human: + return; + self.play(mthd, self.color, depth); + + self.flag_lock = True; + s = ( + str(self.brd.count(True)) + " black stones and " + + str(self.brd.count(False)) + " white stones remain\n" + ); + if status == rv.sts_bwin: + s += "black wins\n"; + elif status == rv.sts_wwin: + s += "white wins\n"; + else: + s += "a tie\n"; + self.print_log(s); + + def click(self, pos): + status = self.brd.get_status(self.color); + + if not (status & rv.sts_turn): + return; + + if self.ply[self.color].type == rv.ply_human: + self.flip(self.color, pos[0], pos[1]); + + self.play(self.mthd, self.color, self.depth); + self.play_continue(); + +reversi.board.config(); +mygame = game(); +mygame.flag_print_term = False; +grp = reversi.group(); + diff --git a/python/main.py b/python/main.py index 22233c0..2dfc889 100644 --- a/python/main.py +++ b/python/main.py @@ -1,21 +1,18 @@ # -*- coding: utf-8 -*- import wx -from wx import xrc -from reversi_gui import * -from wxs2xrc import * +import sys +import os import _thread import time import pdb - -wxsfile = "../wxsmith/reversi_guiframe.wxs"; -xrcfile = "../wxsmith/reversi_guiframe.xrc"; -wxs2xrc(wxsfile,xrcfile); +from game import * rv.pattern.config(); -rv.group.config("ptn_opt.dat") +rv.group.config("../data/pattern.dat") evt_thrd_id = wx.NewId(); + class thrd_event(wx.PyEvent): def __init__(self,data): wx.PyEvent.__init__(self); @@ -24,124 +21,466 @@ def __init__(self,data): class reversi_app(wx.App): + #overload the initializer def OnInit(self): # pdb.set_trace(); - self.res = xrc.XmlResource(xrcfile); + #self.res = xrc.XmlResource(xrcfile); self.init_frame(); return True; + #initialize the frame def init_frame(self): - self.frame = self.res.LoadFrame(None, "reversi_guiFrame"); - self.panel_board = xrc.XRCCTRL(self.frame, "id_panel_board"); - self.text_input = xrc.XRCCTRL(self.frame, "id_text_input"); - self.text_term = xrc.XRCCTRL(self.frame, "id_text_term"); - self.text_log = xrc.XRCCTRL(self.frame, "id_text_log"); - self.choice_black = xrc.XRCCTRL(self.frame, "id_choice_black"); - self.text_path_black = xrc.XRCCTRL(self.frame, "id_text_path_black"); - self.button_folder_black = xrc.XRCCTRL(self.frame, "id_button_folder_black"); - self.choice_white = xrc.XRCCTRL(self.frame, "id_choice_white"); - self.text_path_white = xrc.XRCCTRL(self.frame, "id_text_path_white"); - self.button_folder_white = xrc.XRCCTRL(self.frame, "id_button_folder_white"); - self.button_start = xrc.XRCCTRL(self.frame, "id_button_start"); - self.box_sizer_note = xrc.XRCCTRL(self.frame, "id_panel_note").GetSizer(); - self.menubar = self.frame.GetMenuBar(); - self.menu_trans = self.menubar.FindItemById(xrc.XRCID("id_menu_trans")).GetSubMenu() - self.menu_alg = self.menubar.FindItemById(xrc.XRCID("id_menu_alg")).GetSubMenu(); - self.menu_alg_rnd = self.menubar.FindItemById(xrc.XRCID("id_menu_alg_rnd")); - self.menu_level = self.menubar.FindItemById(xrc.XRCID("id_menu_level")).GetSubMenu(); - self.statusbar = self.frame.GetStatusBar(); - - self.id_menu_trans_mirror_h = xrc.XRCID("id_menu_mirror_h"); - self.id_menu_trans_mirror_v = xrc.XRCID("id_menu_mirror_v"); - self.id_menu_trans_rotate_r = xrc.XRCID("id_menu_rotate_r"); - self.id_menu_trans_rotate_l = xrc.XRCID("id_menu_rotate_l"); - self.id_menu_trans_reflect = xrc.XRCID("id_menu_reflect"); - self.id_menu_trans_reverse = xrc.XRCID("id_menu_reverse"); - - self.id_menu_alg_rnd = xrc.XRCID("id_menu_alg_rnd"); - self.id_menu_alg_ab = xrc.XRCID("id_menu_alg_ab"); - self.id_menu_alg_kill = xrc.XRCID("id_menu_alg_kill"); - self.id_menu_alg_pvs = xrc.XRCID("id_menu_alg_pvs"); - self.id_menu_alg_trans = xrc.XRCID("id_menu_alg_trans"); - self.id_menu_alg_mtdf = xrc.XRCID("id_menu_alg_mtdf"); - self.id_menu_alg_ptn = xrc.XRCID("id_menu_alg_ptn"); - self.id_menu_alg_mpc = xrc.XRCID("id_menu_alg_mpc"); - - self.panel_board.Bind(wx.EVT_PAINT,self.on_panel_board_paint); - self.panel_board.Bind(wx.EVT_LEFT_DOWN,self.on_panel_board_leftdown); - self.text_input.Bind(wx.EVT_TEXT_ENTER,self.on_text_input_textenter); - self.choice_black.Bind(wx.EVT_CHOICE,self.on_choice_player); - self.text_path_black.Bind(wx.EVT_TEXT_ENTER,self.on_text_path_enter); - self.button_folder_black.Bind(wx.EVT_BUTTON,self.on_button_folder_click); - self.choice_white.Bind(wx.EVT_CHOICE,self.on_choice_player); - self.text_path_white.Bind(wx.EVT_TEXT_ENTER,self.on_text_path_enter); - self.button_folder_white.Bind(wx.EVT_BUTTON,self.on_button_folder_click); - self.button_start.Bind(wx.EVT_BUTTON,self.on_start); - self.Bind(wx.EVT_MENU,self.on_quit,id = xrc.XRCID("id_menu_quit")); - self.Bind(wx.EVT_MENU,self.on_about,id = xrc.XRCID("id_menu_about")); - self.Bind(wx.EVT_MENU,self.on_start,id = xrc.XRCID("id_menu_new")); - self.Bind(wx.EVT_MENU,self.on_undo,id = xrc.XRCID("id_menu_undo")); - self.Bind(wx.EVT_MENU,self.on_redo,id = xrc.XRCID("id_menu_redo")); - self.Bind(wx.EVT_MENU,self.on_load,id = xrc.XRCID("id_menu_load")); - self.Bind(wx.EVT_MENU,self.on_eval,id = xrc.XRCID("id_menu_eval")); - self.Bind(wx.EVT_MENU,self.on_clear_log,id = xrc.XRCID("id_menu_clear_log")); - self.Bind(wx.EVT_MENU,self.on_clear_term,id = xrc.XRCID("id_menu_clear_term")); - self.Bind(wx.EVT_MENU,self.on_clear_all,id = xrc.XRCID("id_menu_clear")); - - for item in self.menu_trans.GetMenuItems(): - self.Bind(wx.EVT_MENU,self.on_menu_trans,item); - - for item in self.menu_alg.GetMenuItems(): - self.Bind(wx.EVT_MENU,self.on_menu_alg,item); - - for item in self.menu_level.GetMenuItems(): - self.Bind(wx.EVT_MENU,self.on_menu_level,item); - - self.Connect(-1,-1,evt_thrd_id,self.thrd_catch); - - # Connect(id_book_tree,wxEVT_COMMAND_TREE_ITEM_ACTIVATED,(wxObjectEventFunction)&reversi_guiFrame::on_tree_item_select); - - # self.panel_board.Connect(wxEVT_CONTEXT_MENU,wxContextMenuEventHandler(reversi_guiFrame::on_context_menu),NULL,this); - - size_suit = self.frame.GetBestSize(); - self.frame.SetMinSize(size_suit); - self.frame.SetSize(size_suit); - self.frame.Show(); - self.thrd_lock = False; - mygame.dc = wx.ClientDC(self.panel_board); - mygame.text_log = self.text_log; + #create a frame + self.frame = wx.Frame(); + self.frame.Create(None, wx.ID_ANY, "Reversi"); + font_text = wx.Font(14, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, faceName = "consolas"); + self.frame.SetFont(font_text); + font_index = wx.Font(11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, faceName = "consolas"); + self.frame.SetFont(font_index); + + #set the icon of the frame + frame_icon = wx.Icon(); + frame_icon.CopyFromBitmap(wx.Bitmap(wx.Image("../image/Reversi.bmp"))); + self.frame.SetIcon(frame_icon); + + #create background elements + sizer_base = wx.BoxSizer(wx.HORIZONTAL); + self.frame.SetSizer(sizer_base); + panel_base = wx.Panel(self.frame); + panel_base.SetBackgroundColour(wx.BLACK); + sizer_base.Add(panel_base, 1, wx.ALL | wx.EXPAND,5); + sizer_main = wx.BoxSizer(wx.HORIZONTAL); + panel_base.SetSizer(sizer_main); + + #create a panel for drawing chess board on the left + sizer_board = wx.BoxSizer(wx.VERTICAL); + sizer_main.Add(sizer_board, 0, wx.ALL | wx.ALIGN_CENTER, 5); + self.panel_board = wx.Panel(panel_base, size = wx.Size(424,424), style = wx.SUNKEN_BORDER | wx.TAB_TRAVERSAL); + self.panel_board.SetBackgroundColour(wx.Colour(43,155,0)); + sizer_board.Add(self.panel_board, 1, wx.ALL | wx.ALIGN_CENTER, 5); + + #create a sizer for adding elements on the right + sizer_tool = wx.BoxSizer(wx.VERTICAL); + sizer_main.Add(sizer_tool, 1, wx.ALL | wx.EXPAND, 5); + + #create a label on the top right + text_label = wx.StaticText(panel_base, label = "Reversi"); + sizer_tool.Add(text_label, 0, wx.ALL | wx.ALIGN_CENTER, 5); + text_label.SetForegroundColour(wx.Colour(200,200,200)); + font_text_label = wx.Font(26, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, faceName = "Segoe Script"); + text_label.SetFont(font_text_label); + + #create a notebook on the right + notebook = wx.Notebook(panel_base, size = wx.Size(448,296), style = wx.SUNKEN_BORDER | wx.TAB_TRAVERSAL); + sizer_tool.Add(notebook, 1, wx.ALL | wx.EXPAND, 5); + notebook.SetFont(font_index); + + #add interaction page to the notebook + panel_note = wx.Panel(notebook, style = wx.SUNKEN_BORDER | wx.TAB_TRAVERSAL); + notebook.AddPage(panel_note, "Interaction"); + panel_note.SetForegroundColour(wx.Colour(200,200,200)); + panel_note.SetBackgroundColour(wx.Colour(32,32,32)); + self.sizer_note = wx.BoxSizer(wx.VERTICAL); + panel_note.SetSizer(self.sizer_note); + panel_note.SetFont(font_text); + + #specify black player in the interaction page + self.sizer_note_black = wx.BoxSizer(wx.HORIZONTAL); + self.sizer_note.Add(self.sizer_note_black, 1, wx.ALL | wx.ALIGN_CENTER, 5); + + label_black = wx.StaticText(panel_note, label = "Black Player"); + self.sizer_note_black.Add(label_black, 1, wx.ALL | wx.ALIGN_CENTER, 5); + + self.choice_black = wx.Choice(panel_note); + self.choice_black.SetSelection(self.choice_black.Append("Human")); + self.choice_black.Append("Computer"); + self.choice_black.Append("Other Program"); + self.choice_black.SetForegroundColour(wx.Colour(32,32,32)); + self.choice_black.SetBackgroundColour(wx.Colour(200,200,200)); + self.sizer_note_black.Add(self.choice_black, 1, wx.ALL | wx.ALIGN_CENTER, 5); + + #specify black player path in the interaction page + self.sizer_note_path_black = wx.BoxSizer(wx.HORIZONTAL); + self.sizer_note.Add(self.sizer_note_path_black, 1, wx.ALL | wx.ALIGN_CENTER, 5); + + self.text_path_black = wx.TextCtrl( + panel_note, value = "bot/Irius", + size = (332,30), style = wx.TE_PROCESS_ENTER + ); + self.text_path_black.SetBackgroundColour(wx.Colour(200,200,200)); + self.sizer_note_path_black.Add(self.text_path_black, 1, wx.ALL | wx.ALIGN_CENTER, 5); self.text_path_black.Hide(); + + self.button_folder_black = wx.BitmapButton( + panel_note, bitmap = wx.Bitmap(wx.Image("../image/folder_small.png")), size = wx.Size(32,29) + ); + self.button_folder_black.SetBackgroundColour(wx.Colour(0,0,0)); + self.sizer_note_path_black.Add(self.button_folder_black, 0, wx.ALL | wx.ALIGN_CENTER, 5); self.button_folder_black.Hide(); + + #specify white player in the interaction page + self.sizer_note_white = wx.BoxSizer(wx.HORIZONTAL); + self.sizer_note.Add(self.sizer_note_white, 1, wx.ALL | wx.ALIGN_CENTER, 5); + + label_white = wx.StaticText(panel_note, label = "White Player"); + self.sizer_note_white.Add(label_white, 1, wx.ALL | wx.ALIGN_CENTER, 5); + + self.choice_white = wx.Choice(panel_note); + self.choice_white.Append("Human"); + self.choice_white.SetSelection(self.choice_white.Append("Computer")); + self.choice_white.Append("Other Program"); + self.choice_white.SetForegroundColour(wx.Colour(32,32,32)); + self.choice_white.SetBackgroundColour(wx.Colour(200,200,200)); + self.sizer_note_white.Add(self.choice_white, 1, wx.ALL | wx.ALIGN_CENTER, 5); + + #specify white player path in the interaction page + self.sizer_note_path_white = wx.BoxSizer(wx.HORIZONTAL); + self.sizer_note.Add(self.sizer_note_path_white, 1, wx.ALL | wx.ALIGN_CENTER, 5); + + self.text_path_white = wx.TextCtrl( + panel_note, value = "bot/Irius", + size = (332,30), style = wx.TE_PROCESS_ENTER + ); + self.text_path_white.SetBackgroundColour(wx.Colour(200,200,200)); + self.sizer_note_path_white.Add(self.text_path_white, 1, wx.ALL | wx.ALIGN_CENTER, 5); self.text_path_white.Hide(); + + self.button_folder_white = wx.BitmapButton( + panel_note, bitmap = wx.Bitmap(wx.Image("../image/folder_small.png")), size = wx.Size(32,29) + ); + self.button_folder_white.SetBackgroundColour(wx.Colour(0,0,0)); + self.sizer_note_path_white.Add(self.button_folder_white, 0, wx.ALL | wx.ALIGN_CENTER, 5); self.button_folder_white.Hide(); - self.box_sizer_note.Layout(); + + #add start button to the interaction page + self.sizer_note_start = wx.BoxSizer(wx.HORIZONTAL); + self.sizer_note.Add(self.sizer_note_start, 1, wx.ALL | wx.ALIGN_CENTER, 5); + + self.button_start = wx.Button(panel_note, label = "Start a New Game"); + #self.button_start.SetForegroundColour(wx.Colour(32,32,32)); + #self.button_start.SetBackgroundColour(wx.Colour(200,200,200)); + self.sizer_note_start.Add(self.button_start, 1, wx.ALL | wx.ALIGN_CENTER, 5); + + #add terminal page to the notebook + self.text_term = wx.TextCtrl(notebook, style = wx.TE_MULTILINE | wx.TE_READONLY); + notebook.AddPage(self.text_term, "Terminal"); + self.text_term.SetForegroundColour(wx.Colour(200,200,200)); + self.text_term.SetBackgroundColour(wx.Colour(32,32,32)); + self.text_term.SetFont(font_text); + + #add log page to the notebook + self.text_log = wx.TextCtrl(notebook, style = wx.TE_MULTILINE | wx.TE_READONLY); + notebook.AddPage(self.text_log, "Log"); + self.text_log.SetForegroundColour(wx.Colour(200,200,200)); + self.text_log.SetBackgroundColour(wx.Colour(32,32,32)); + self.text_log.SetFont(font_text); + + #create a input box on the bottom right + self.text_input = wx.TextCtrl(panel_base, size = wx.Size(266,30), style = wx.TE_PROCESS_ENTER | wx.TE_PROCESS_TAB); + sizer_tool.Add(self.text_input, 0, wx.ALL | wx.ALIGN_CENTER | wx.EXPAND, 5); + self.text_input.SetForegroundColour(wx.Colour(200,200,200)); + self.text_input.SetBackgroundColour(wx.Colour(32,32,32)); + self.text_input.SetFont(font_text); + + #create a menu bar + self.menubar = wx.MenuBar(); + self.frame.SetMenuBar(self.menubar); + menu_file = wx.Menu(); + self.menubar.Append(menu_file, "&File"); + menu_edit = wx.Menu(); + self.menubar.Append(menu_edit, "&Edit"); + menu_setting = wx.Menu(); + self.menubar.Append(menu_setting, "&Setting"); + menu_help = wx.Menu(); + self.menubar.Append(menu_help, "&Help"); + + #add items to menu_file + menu_new = wx.MenuItem( + menu_file, id = wx.NewId(), + text = "&New Game\tCtrl-N", + helpString = "Start a new game" + ); + menu_file.Append(menu_new); + menu_load = wx.MenuItem( + menu_file, id = wx.NewId(), + text = "&Load Script\tCtrl-L", + helpString = "Load and execute a Python script" + ); + menu_file.Append(menu_load); + menu_export = wx.MenuItem( + menu_file, id = wx.NewId(), + text = "&Export Image\tCtrl-S", + helpString = "Export the board as an image" + ); + menu_file.Append(menu_export); + menu_quit = wx.MenuItem( + menu_file, id = wx.NewId(), + text = "&Quit\tAlt-F4", + helpString = "Quit the application" + ); + menu_file.Append(menu_quit); + + #add items to menu_edit + menu_undo = wx.MenuItem( + menu_edit, id = wx.NewId(), + text = "&Undo\tCtrl+Z", + helpString = "Undo the latest change" + ); + menu_edit.Append(menu_undo); + menu_redo = wx.MenuItem( + menu_edit, id = wx.NewId(), + text = "&Redo\tCtrl+Y", + helpString = "Redo the latest change" + ); + menu_edit.Append(menu_redo); + menu_transform = wx.Menu(); + menu_edit.Append(wx.NewId(), "&Transform", menu_transform); + menu_eval = wx.MenuItem( + menu_edit, id = wx.NewId(), + text = "&Evaluate\tCtrl+E", + ); + menu_edit.Append(menu_eval); + menu_clear = wx.Menu(); + menu_edit.Append(wx.NewId(), "&Clear", menu_clear); + + #add items to menu_transform + menu_mirror_h = wx.MenuItem( + menu_transform, id = wx.NewId(), + text = "Mirror &Horrizontally\tAlt+H" + ); + menu_mirror_h.num = 0; + menu_transform.Append(menu_mirror_h); + menu_mirror_v = wx.MenuItem( + menu_transform, id = wx.NewId(), + text = "Mirror &Vertically\tAlt+V" + ); + menu_mirror_v.num = 1; + menu_transform.Append(menu_mirror_v); + menu_reflect = wx.MenuItem( + menu_transform, id = wx.NewId(), + text = "&Reflect\tAlt+R" + ); + menu_reflect.num = 2; + menu_transform.Append(menu_reflect); + menu_rotate_r = wx.MenuItem( + menu_transform, id = wx.NewId(), + text = "Rotate &Clockwise\tAlt+C" + ); + menu_rotate_r.num = 3; + menu_transform.Append(menu_rotate_r); + menu_rotate_l = wx.MenuItem( + menu_transform, id = wx.NewId(), + text = "Rotate Coun&terclockwise\tAlt+T" + ); + menu_rotate_l.num = 4; + menu_transform.Append(menu_rotate_l); + menu_reverse = wx.MenuItem( + menu_transform, id = wx.NewId(), + text = "Rever&se\tAlt+S" + ); + menu_reverse.num = 5; + menu_transform.Append(menu_reverse); + + #add items to menu_clear + menu_clear_term = wx.MenuItem( + menu_clear, id = wx.NewId(), + text = "Clear Terminal" + ); + menu_clear.Append(menu_clear_term); + menu_clear_log = wx.MenuItem( + menu_clear, id = wx.NewId(), + text = "Clear Log" + ); + menu_clear.Append(menu_clear_log); + + #add items to menu_setting + self.menu_algorithm = wx.Menu(); + menu_setting.Append(wx.NewId(), "&Algorithm", self.menu_algorithm); + self.menu_level = wx.Menu(); + menu_setting.Append(wx.NewId(), "&Level", self.menu_level); + + #add items to menu_algorithm + alg_table = [ + rv.mthd_rnd, rv.mthd_ab, rv.mthd_pvs, rv.mthd_trans, + rv.mthd_kill, rv.mthd_mtdf, rv.mthd_ids, rv.mthd_ptn, + rv.mthd_mpc + ]; + alg_str_table = [ + "rv.mthd_rnd", "rv.mthd_ab", "rv.mthd_pvs", "rv.mthd_trans", + "rv.mthd_kill", "rv.mthd_mtdf", "rv.mthd_ids", "rv.mthd_ptn", + "rv.mthd_mpc" + ]; + alg_text_table = [ + "&Random", "&Alpha-Beta Pruning", "Principle &Variation Search", "&Transposition Table", + "&Killer Heuristic", "&Memory Enhanced Test Driver", "&Iterative Deepening Search", "&Pattern", + "Multi-Probability &Cut" + ]; + for i in range(len(alg_table)): + menu_alg = wx.MenuItem( + self.menu_algorithm, id = wx.NewId(), + text = alg_text_table[i], + kind = wx.ITEM_CHECK + ); + menu_alg.mthd = alg_table[i]; + menu_alg.mthd_str = alg_str_table[i]; + self.menu_algorithm.Append(menu_alg); + if alg_table[i] & mygame.mthd: + menu_alg.Check(True); + self.menu_algorithm.Insert(1, wx.NewId(), kind = wx.ITEM_SEPARATOR); + + #add items to menu_level + for i in range(10): + self.menu_level.Append( + wx.MenuItem( + self.menu_level, id = wx.NewId(), + text = "Level %d" % (i + 1), + kind = wx.ITEM_CHECK + ) + ); + self.menu_level.GetMenuItems()[7].Check(True); + + #add items to menu_help + menu_about = wx.MenuItem( + menu_help, id = wx.NewId(), + text = "&About\tF1", + helpString = "Show info about this application" + ); + menu_help.Append(menu_about); + + #create a status bar + self.statusbar = wx.StatusBar(self.frame); + self.statusbar.SetFieldsCount(3, (-1, -1, -1)); + self.statusbar.SetStatusStyles((wx.SB_NORMAL, wx.SB_NORMAL, wx.SB_NORMAL)); + self.frame.SetStatusBar(self.statusbar); + + #set the suitable size of the frame + sizer_base.SetSizeHints(self.frame); + + #bind interaction events + self.panel_board.Bind(wx.EVT_PAINT, self.on_panel_board_paint); + self.panel_board.Bind(wx.EVT_LEFT_DOWN, self.on_panel_board_leftdown); + self.text_input.Bind(wx.EVT_TEXT_ENTER, self.on_text_input_textenter); + self.choice_black.Bind(wx.EVT_CHOICE, self.on_choice_player); + self.text_path_black.Bind(wx.EVT_TEXT_ENTER, self.on_text_path_enter); + self.button_folder_black.Bind(wx.EVT_BUTTON, self.on_button_folder_click); + self.choice_white.Bind(wx.EVT_CHOICE, self.on_choice_player); + self.text_path_white.Bind(wx.EVT_TEXT_ENTER, self.on_text_path_enter); + self.button_folder_white.Bind(wx.EVT_BUTTON, self.on_button_folder_click); + self.button_start.Bind(wx.EVT_BUTTON, self.on_start); + self.Bind(wx.EVT_MENU, self.on_start, id = menu_new.GetId()); + self.Bind(wx.EVT_MENU, self.on_load, id = menu_load.GetId()); + self.Bind(wx.EVT_MENU, self.on_export, id = menu_export.GetId()); + self.Bind(wx.EVT_MENU, self.on_quit, id = menu_quit.GetId()); + self.Bind(wx.EVT_MENU, self.on_undo, id = menu_undo.GetId()); + self.Bind(wx.EVT_MENU, self.on_redo, id = menu_redo.GetId()); + self.Bind(wx.EVT_MENU, self.on_eval, id = menu_eval.GetId()); + self.Bind(wx.EVT_MENU, self.on_clear_log, id = menu_clear_log.GetId()); + self.Bind(wx.EVT_MENU, self.on_clear_term, id = menu_clear_term.GetId()); + self.Bind(wx.EVT_MENU, self.on_about, id = menu_about.GetId()); + + for i in menu_transform.GetMenuItems(): + self.Bind(wx.EVT_MENU, self.on_menu_trans, i); + + for i in self.menu_algorithm.GetMenuItems(): + self.Bind(wx.EVT_MENU, self.on_menu_alg, i); + + for i in self.menu_level.GetMenuItems(): + self.Bind(wx.EVT_MENU, self.on_menu_level, i); + + self.Connect(-1, -1, evt_thrd_id, self.thrd_catch); + + #show the frame + self.frame.Show(True); + + #define a function which prints strings on text_term + global _print; + _print = lambda *args: self.text_term.AppendText(" ".join([str(x) for x in args]) + "\n"); + + self.thrd_lock = False; + mygame.panel_board = self.panel_board; + mygame.dc = wx.ClientDC(self.panel_board); + mygame.text_log = self.text_log; + + #process command + def process(self, s): + if self.thrd_lock: + return; + self.text_term.AppendText(">>" + s + "\n"); + time_start = time.time(); + #try: + exec(s); + #except: + # self.info = sys.exc_info(); + # _print(sys.exc_info()[1]); + time_end = time.time(); + self.statusbar.SetStatusText("Wall time : %f seconds" % (time_end - time_start), 2); + + #input command + def on_text_input_textenter(self, event): + self.process(self.text_input.GetValue()); def on_quit(self,event): - self.Close(); + self.frame.Close(); + def on_about(self,event): - wx.MessageBox("Reversi Game\nBy Rick\n1300012743@pku.edu.cn","About"); + wx.MessageBox("Reversi Game\nBy Rick", "About"); + + #paint on panel_board def on_panel_board_paint(self, event): self.paint(); + + #paint on panel_board def paint(self): dc = wx.ClientDC(self.panel_board); - mygame.do_show(dc) - def _print(self,s): - self.text_term.AppendText(str(s) + "\n"); - def process(self,s): - if self.thrd_lock: - return; - self.text_term.AppendText(">>" + s + "\n"); - time_start = time.clock(); - exec(s); - time_end = time.clock(); - self.statusbar.SetStatusText("Execution time : %f seconds" % (time_end - time_start),0); - def on_text_input_textenter(self,event): - self.process(self.text_input.GetValue()); - def on_choice_player(self,event): + mygame.do_show(dc); + + #click on the panel board + def on_panel_board_leftdown(self,event): + # if mygame.is_lock: + # return; + pos = event.GetPosition(); + if pos.x < bias: + x = -1; + else: + x = int((pos.x - bias) / cell); + if pos.y < bias: + y = -1; + else: + y = int((pos.y - bias) / cell); + self.process("mygame.click((%d,%d));" % (x,y)); + + #export image + def on_export(self, event): + dialog_export = wx.FileDialog(self.frame, message = "Export image", wildcard = "*.png", style = wx.FD_SAVE); + + if dialog_export.ShowModal() == wx.ID_OK: + path = dialog_export.GetPath(); + path = path.replace("\\","\\\\"); + self.process("mygame.export(\"" + path + "\", img_type = wx.BITMAP_TYPE_PNG);\n"); + + #load and execute a script + def load_script(self, s): + fobj = open(s); + lines = fobj.readlines(); + fobj.close(); + lines = "\n".join(lines); + exec(lines); + return True; + + #load and execute a script + def on_load(self, event): + dialog_load = wx.FileDialog(self.frame, message = "Load a python script", wildcard = "*.py", style = wx.FD_OPEN); + + if dialog_load.ShowModal() == wx.ID_OK: + path = dialog_load.GetPath(); + path = path.replace("\\","\\\\"); + self.process("self.load_script(\"" + path + "\");\n"); + + def on_choice_player(self, event): if event.GetId() == self.choice_black.GetId(): self.process( - "mygame.get_ply(True).p_type = " + "mygame.ply[True].type = " + str(self.choice_black.GetCurrentSelection()) + ";" ); @@ -153,11 +492,11 @@ def on_choice_player(self,event): self.text_path_black.Hide(); self.button_folder_black.Hide(); - self.box_sizer_note.Layout(); + self.sizer_note.Layout(); elif event.GetId() == self.choice_white.GetId(): self.process( - "mygame.get_ply(False).p_type = " + "mygame.ply[False].type = " + str(self.choice_white.GetCurrentSelection()) + ";" ); @@ -169,21 +508,22 @@ def on_choice_player(self,event): self.text_path_white.Hide(); self.button_folder_white.Hide(); - self.box_sizer_note.Layout(); + self.sizer_note.Layout(); def on_text_path_enter(self,event): if event.GetId() == self.text_path_black.GetId(): self.process( - "mygame.get_ply(True).path = \"" - + self.text_path_black.GetValue() + "mygame.ply[True].path = \"" + + self.text_path_black.GetValue().replace("\\","\\\\") + "\";" ); elif event.GetId() == self.text_path_white.GetId(): self.process( - "mygame.get_ply(False).path = \"" - + self.text_path_white.GetValue() + "mygame.ply[False].path = \"" + + self.text_path_white.GetValue().replace("\\","\\\\") + "\";" ); + def on_button_folder_click(self,event): if event.GetId() == self.button_folder_black.GetId(): dialog_choice_player = wx.FileDialog( @@ -194,10 +534,10 @@ def on_button_folder_click(self,event): if dialog_choice_player.ShowModal() == wx.ID_OK: path = dialog_choice_player.GetPath(); - path = path.replace("\\","\\\\"); self.text_path_black.SetValue(path); + path = path.replace("\\","\\\\"); self.process( - "mygame.get_ply(True).path = \"" + "mygame.ply[True].path = \"" + path + "\";" ); @@ -210,135 +550,87 @@ def on_button_folder_click(self,event): if dialog_choice_player.ShowModal() == wx.ID_OK: path = dialog_choice_player.GetPath(); - path = path.replace("\\","\\\\"); self.text_path_white.SetValue(path); + path = path.replace("\\","\\\\"); self.process( - "mygame.get_ply(False).path = \"" + "mygame.ply[False].path = \"" + path + "\";" ); + + #start a new game def on_start(self,event): self.process("mygame.start();"); + def on_undo(self,event): self.process("mygame.undo();"); + def on_redo(self, event): self.process("mygame.redo();"); - def on_load(self, event): - pass; - # if self.dialog_load.ShowModal() == wxID_OK: - # path = self.dialog_load.GetPath(); - # pos = 0; - # path = path.replace("\\","\\\\"); - # self.process("load " + path); + def on_menu_trans(self, event): - id = event.GetId(); - if id == self.id_menu_trans_mirror_h: + num = self.menubar.FindItemById(event.GetId()).num; + if num == 0: self.process("mygame.mirror_h();"); - if id == self.id_menu_trans_mirror_v: + elif num == 1: self.process("mygame.mirror_v();"); - if id == self.id_menu_trans_reflect: + elif num == 2: self.process("mygame.reflect();"); - if id == self.id_menu_trans_rotate_r: + elif num == 3: self.process("mygame.rotate_r();"); - if id == self.id_menu_trans_rotate_l: + elif num == 4: self.process("mygame.rotate_l();"); - if id == self.id_menu_trans_reverse: + elif num == 5: self.process("mygame.reverse();"); + def on_eval(self,event): self.process("_print(mygame.get_choice(mygame.mthd,mygame.color,mygame.depth));"); + def on_clear_log(self, event): self.process("self.text_log.Clear();"); + def on_clear_term(self, event): self.process("self.text_term.Clear();"); + def on_clear_all(self, event): self.process("self.text_log.Clear();"); self.process("self.text_term.Clear();"); - def on_panel_board_leftdown(self,event): - # if mygame.is_lock: - # return; - pos = event.GetPosition(); - if pos.x < bias: - x = -1; - else: - x = int((pos.x - bias) / cell); - if pos.y < bias: - y = -1; - else: - y = int((pos.y - bias) / cell); - self.process( - "_print(" - "mygame.play(" - "rv.coordinate(%d,%d)" - ")" - ");" - % (x,y) - ); + def on_menu_alg(self,event): id = event.GetId(); - item = self.menu_alg.FindItemById(id); + item = self.menu_algorithm.FindItemById(id); - if id == self.id_menu_alg_rnd: - if self.menu_alg_rnd.IsChecked(): - for ptr in self.menu_alg.GetMenuItems(): + if item.mthd == rv.mthd_rnd: + if self.menu_algorithm.GetMenuItems()[0].IsChecked(): + for ptr in self.menu_algorithm.GetMenuItems(): if ptr.IsCheckable(): ptr.Check(False); - self.process("mygame.mthd = rv.mthd_rnd") - self.menu_alg_rnd.Check(True); + self.process("mygame.mthd = rv.mthd_rnd;") + self.menu_algorithm.GetMenuItems()[0].Check(True); else: if item.IsChecked(): - item.Check(True); - self.menu_alg_rnd.Check(False); - - if id == self.id_menu_alg_ab: - self.process("mygame.mthd |= rv.mthd_ab"); - elif id == self.id_menu_alg_kill: - self.process("mygame.mthd |= rv.mthd_kill"); - elif id == self.id_menu_alg_pvs: - self.process("mygame.mthd |= rv.mthd_pvs"); - elif id == self.id_menu_alg_trans: - self.process("mygame.mthd |= rv.mthd_trans"); - elif id == self.id_menu_alg_mtdf: - self.process("mygame.mthd |= rv.mthd_mtdf"); - elif id == self.id_menu_alg_ptn: - self.process("mygame.mthd |= rv.mthd_ptn"); - elif id == self.id_menu_alg_mpc: - self.process("mygame.mthd |= rv.mthd_mpc"); + self.menu_algorithm.GetMenuItems()[0].Check(False); + self.process("mygame.mthd |= " + item.mthd_str + ";"); else: flag = False; - for ptr in self.menu_alg.GetMenuItems(): - if ptr.IsChecked(): + for ptr in self.menu_algorithm.GetMenuItems(): + if ptr.IsCheckable() and ptr.IsChecked(): flag = True; if not flag: - self.menu_alg_rnd.Check(True); - - if id == self.id_menu_alg_ab: - self.process("mygame.mthd &= ~rv.mthd_ab"); - elif id == self.id_menu_alg_kill: - self.process("mygame.mthd &= ~rv.mthd_kill"); - elif id == self.id_menu_alg_pvs: - self.process("mygame.mthd &= ~rv.mthd_pvs"); - elif id == self.id_menu_alg_trans: - self.process("mygame.mthd &= ~rv.mthd_trans"); - elif id == self.id_menu_alg_mtdf: - self.process("mygame.mthd &= ~rv.mthd_mtdf"); - elif id == self.id_menu_alg_ptn: - self.process("mygame.mthd &= ~rv.mthd_ptn"); - elif id == self.id_menu_alg_mpc: - self.process("mygame.mthd &= ~rv.mthd_mpc"); + self.menu_algorithm.GetMenuItems()[0].Check(True); - def on_menu_level(self,event): - for item in self.menu_level.GetMenuItems(): - item.Check(False); + self.process("mygame.mthd &= ~" + item.mthd_str + ";"); + def on_menu_level(self,event): pos = 0; - (item,pos) = self.menu_level.FindChildItem(event.GetId()); + for i in self.menu_level.GetMenuItems(): + i.Check(False); + (item, pos) = self.menu_level.FindChildItem(event.GetId()); item.Check(True); - if pos == 7: - pos = -1; - elif pos == 8: - pos = -2; - elif pos == 9: - pos = -3; + if pos >= 7: + pos = 6 - pos; + else: + pos = pos + 1; self.process("mygame.depth = %d" % pos); @@ -347,20 +639,23 @@ def thrd_launch(self,fun,param): try: _thread.start_new_thread(self.thrd_wrap,(fun,param)); except: - self._print("fail to launch the thread!"); + _print("fail to launch the thread!"); self.thrd_lock = False; + def thrd_catch(self,event): self.thrd_lock = False; + def thrd_wrap(self,fun,param): try: result = fun(*param); except: - self._print("fail to launch the thread!"); + _print("fail to launch the thread!"); self.thrd_lock = False; wx.PostEvent(self,thrd_event(None)); + def sleep(self,count): time.sleep(count); - self._print("sleep for %d seconds" % count); + _print("sleep for %d seconds" % count); # def on_context_menu(wxContextMenuEvent& event){ # //wxMenu* menu = new wxMenu(); @@ -403,6 +698,4 @@ def sleep(self,count): if __name__ == "__main__": app = reversi_app(False); - def _print(s): - return app._print(s); - app.MainLoop(); \ No newline at end of file + app.MainLoop(); diff --git a/python/makefile b/python/makefile index 1ac83a4..88801a0 100644 --- a/python/makefile +++ b/python/makefile @@ -1,26 +1,58 @@ -pylib_path = /lib/python2.7/config/ -pyhead_path = /usr/include/python2.7/ -src_path = ../ +WORKDIR = `pwd` -src = $(addprefix $(src_path),type.cc reversi.cc flip.cc search.cc pattern.cc tree.cc) -head = $(addprefix $(src_path),type.h asm.h reversi.h matrix.h pattern.h game.h tree.h) -obj = reversi_wrap.o type.o reversi.o flip.o search.o pattern.o tree.o -target = _reversi.cp35-win_amd64.pyd +CC = gcc +CXX = g++ +AR = ar +LD = g++ +WINDRES = windres +RM = rm -f -cc = gcc -cxx = g++ -compile_option = -Wall -std=c++11 -O2 -c +INC = -I/usr/include/python3.5/ +CFLAGS = +CXXFLAGS = -Wall -g -Og -std=c++11 -fPIC +RESINC = +LIBDIR = -L/usr/lib/python3.5/config-3.5m-x86_64-linux-gnu/ +LIB = +LDFLAGS = -shared -lpython3.5 -.PHONY: all clean +SRCDIR = ../cpp/ +OBJDIR = obj/ +OUTDIR = ./ -all: $(target) +SRC = $(wildcard $(SRCDIR)*.cc) +HEAD = $(wildcard $(SRCDIR)*.h) +OBJ = $(OBJDIR)reversi_wrap.o $(patsubst $(SRCDIR)%.cc, $(OBJDIR)%.o, $(SRC)) +OUT = $(OUTDIR)_reversi.so + +.PHONY: all clean before + +all: before $(OUT) + +before: + test -d $(OBJDIR) || mkdir -p $(OBJDIR) + test -d $(OUTDIR) || mkdir -p $(OUTDIR) clean: - -del *.o *.cxx *.pyd *.pyc *.exe *.dll + -$(RM) $(OBJDIR)*.o + -$(RM) $(addprefix $(OUTDIR), *wrap* reversi.py *.exe *.dll *.so *.pyd) + +$(OUT): $(OBJ) + $(LD) $(LDFLAGS) $(LIBDIR) $(OBJ) -o $@ + +$(OBJDIR)reversi.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM $(SRCDIR)reversi.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(OBJDIR)flip.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM $(SRCDIR)flip.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(OBJDIR)search.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM $(SRCDIR)search.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(OBJDIR)pattern.o: $(wordlist 2,100,$(shell g++ -std=c++11 -MM $(SRCDIR)pattern.cc | awk -f parse.awk)) + $(CXX) $(CXXFLAGS) -c $< -o $@ -$(target): reversi_wrap.cxx setup.py $(src) - python setup.py build_ext --inplace --compiler=mingw32 +$(OUTDIR)reversi_wrap.cxx: $(OUTDIR)reversi.i $(HEAD) + swig -python -c++ -threads -o $@ $< -reversi_wrap.cxx: reversi.i $(head) - swig -python -c++ -threads $< - python patch.py \ No newline at end of file +$(OBJDIR)reversi_wrap.o: $(OUTDIR)reversi_wrap.cxx + $(CXX) $(CXXFLAGS) $(INC) -c $< -o $@ diff --git a/python/opening_train.py b/python/opening_train.py deleted file mode 100644 index 8044d56..0000000 --- a/python/opening_train.py +++ /dev/null @@ -1,12 +0,0 @@ - -import reversi as rv -a = rv.pos_array(10); -t = rv.tree(); - -for i in range(100): - t.practice(rv.mthd_ab,4); - -t.practice(rv.mthd_ab,4); - -# t._print(); -# t.save("temp.dat"); \ No newline at end of file diff --git a/python/parse.awk b/python/parse.awk new file mode 100644 index 0000000..19881cf --- /dev/null +++ b/python/parse.awk @@ -0,0 +1,9 @@ +BEGIN {} +{ + for (i = 1; i <= NF; ++i) { + if($i != "\\"){ + printf "%s ", $i + } + } +} +END {printf "\n"} diff --git a/python/patch.py b/python/patch.py deleted file mode 100644 index 9da4c82..0000000 --- a/python/patch.py +++ /dev/null @@ -1,12 +0,0 @@ -import re - -filename = "reversi_wrap.cxx"; -fobj = open(filename,"r"); -lines = fobj.readlines(); -fobj.close(); - -lines = [re.sub(r"std::matrix",r"matrix",line) for line in lines]; - -fobj = open(filename,"w"); -lines = fobj.writelines(lines); -fobj.close(); \ No newline at end of file diff --git a/python/pattern_train.py b/python/pattern_train.py deleted file mode 100644 index d8d60fd..0000000 --- a/python/pattern_train.py +++ /dev/null @@ -1,20 +0,0 @@ -import reversi as rv - -def train(mthd,depth,size,num): - brd = rv.board(); - brd.config(); - - grp = rv.group(); - - mthd_full = "mthd_" + mthd - mthd_id = getattr(rv,mthd_full) - - grp.assign(size); - grp.initial(); - - for i in range(num): - grp.train(mthd_id,depth); - - name = "ptn_%s_d%ds%dn%d" % (mthd,depth,size,num) - grp.save(name + ".dat"); - print(name); \ No newline at end of file diff --git a/python/predict.py b/python/predict.py new file mode 100644 index 0000000..4696695 --- /dev/null +++ b/python/predict.py @@ -0,0 +1,91 @@ +import numpy as np; +import time; +import pickle; +import json; +import zipfile; +import os; +import signal; +import pysigset; + +import reversi as rv; +rv.board.config(); +rv.pattern.config(); +rv.group.config("data/pattern.dat"); +mthd = rv.mthd_ab | rv.mthd_kill | rv.mthd_pvs | rv.mthd_trans | rv.mthd_mtdf | rv.mthd_ptn; + +data_path = "../data/"; + +flag_int = False; +def on_interrupt(signum, frame): + global flag_int; + flag_int = True; + +def generate_table(sample, begin = None): + assert(os.path.exists(data_path + sample)); + with open(data_path + sample, "rb") as fobj: + sample = pickle.load(fobj); + + if not os.path.exists(data_path + "table.dat"): + table = np.zeros((65, 32, 32, 4)); + table[:, :, :, 2] = 1; + with open(data_path + "table.dat", "wb") as fobj: + pickle.dump([table, [0, 0]], fobj); + + with open(data_path + "table.dat", "rb") as fobj: + [table, num] = pickle.load(fobj); + + if not (begin is None): + num = begin; + + handler_save = signal.signal(signal.SIGINT, on_interrupt); + + for i in range(num[0], len(sample)): + sub_sample = sample[i]; + + for ii in range(num[1], sub_sample.shape[0]): + brd = rv.board(); + brd.assign(int(sub_sample[ii, 1]), int(sub_sample[ii, 0])); + cnt = brd.sum(); + + childid = os.fork(); + if childid > 0: + time.sleep(4); + os.kill(childid, signal.SIGUSR1); + os.wait(); + print("finish", i, ii); + if flag_int: + signal.signal(signal.SIGINT, handler_save); + return; + else: + with open(data_path + "table.dat", "rb") as fobj: + [table, num] = pickle.load(fobj); + + num[1] += 1; + if num[1] == len(sample[num[0]]): + num[0] += 1; + num[1] = 0; + + record = []; + for j in range(0, 32): + pmthd = brd.process_method(mthd, j); + record.append(brd.search(pmthd.first, True, pmthd.second)); + for k in range(0, j): + l = table[cnt, k, j, 0]; + r = sub_sample[ii, 2]; + bias = record[j] - record[k]; + table[cnt, k, j, 0] = l + r; + table[cnt, k, j, 2] *= l / (l + r); + table[cnt, k, j, 2] += abs(bias - table[cnt, k, j, 1]) * r / (l + r); + table[cnt, k, j, 1] *= l / (l + r); + table[cnt, k, j, 1] += bias * r / (l + r); + if j >= 5: + with pysigset.suspended_signals(signal.SIGUSR1): + with open(data_path + "table.dat", "wb") as fobj: + pickle.dump([table, num], fobj); + + signal.signal(signal.SIGINT, handler_save); + return; + + num[1] = 0; + +generate_table("Reversi-2018-2.dat"); diff --git a/python/reversi.i b/python/reversi.i index 8f6d96c..0b3e9c3 100644 --- a/python/reversi.i +++ b/python/reversi.i @@ -3,28 +3,25 @@ %include %include %include -%include %include %include %feature("director") game; %{ -#include "../type.h" -#include "../asm.h" -#include "../reversi.h" -#include "../game.h" -#include "../matrix.h" -#include "../pattern.h" -#include "../tree.h" +#include "../cpp/type.h" +#include "../cpp/asm.h" +#include "../cpp/reversi.h" +#include "../cpp/matrix.h" +#include "../cpp/pattern.h" +#include "../cpp/log.h" %} -%include "../type.h" -%include "../reversi.h" -%include "../matrix.h" -%include "../pattern.h" -%include "../game.h" -%include "../tree.h" +%include "../cpp/type.h" +%include "../cpp/reversi.h" +%include "../cpp/matrix.h" +%include "../cpp/pattern.h" +%include "../cpp/log.h" %template(shorts) std::vector; %template(ints) std::vector; @@ -32,7 +29,6 @@ %template(boards) std::vector; %template(choices) std::vector; %template(patterns) std::vector; -//%template(samples) std::unordered_set; %template(pair_method) std::pair; %template(mat_i) matrix; %template(mat_f) matrix; @@ -41,4 +37,5 @@ %array_class(pos_type, pos_array); %rename(__eq__) board::operator==; -%ignore board::operator<<(ostream& out,const board& brd); \ No newline at end of file +%rename(__neq__) board::operator!=; +%ignore board::operator<<(ostream& out,const board& brd); diff --git a/python/reversi_gui.py b/python/reversi_gui.py deleted file mode 100644 index 137f130..0000000 --- a/python/reversi_gui.py +++ /dev/null @@ -1,174 +0,0 @@ -# -*- coding: utf-8 -*- - -import wx -import reversi -import reversi as rv -import json -import subprocess as sp - -bias = 34; -num = 8; -cell = 44; -width = num * cell; -cbias = bias + cell / 2; -radius = cell / 2 - 4; -thick = 3; -margin = 20; - -grp = reversi.group(); - -def coord2str(self): - return "(%d,%d)" % (self.x,self.y); -setattr(reversi.coordinate,"__str__",coord2str); - -def choice2str(self): - return "(%d,%d,%f)" % (self.pos & 7,self.pos >> 3,self.val); -setattr(reversi.choice,"__str__",choice2str); - -def choices2str(self): - return "[" + ",".join([choice2str(c) for c in self]) + "]"; -setattr(reversi.choices,"__str__",choices2str); - -def floats2str(self): - return "[" + ",".join([str(f) for f in self]) + "]"; -setattr(reversi.floats,"__str__",floats2str) - -class game_gui(reversi.game): - def show(self): - self.do_show(self.dc); - - def do_show(self,dc): - dc.Clear(); - - #draw valid moves - dc.SetBrush(wx.Brush(wx.Colour(30,100,0))); - dc.SetPen(wx.Pen(wx.Colour(30,100,0),thick)); - brd_move = self.brd.get_move(self.color); - for i in range(reversi.board.size2): - if brd_move & (1 << i): - dc.DrawRectangle(bias + cell * (i & 7),bias + cell * (i >> 3),cell,cell); - - #draw a board - dc.SetPen(wx.Pen(wx.BLACK,thick)); - for i in range(num + 1): - dc.DrawLine(bias,bias + cell * i,bias + width,bias + cell * i); - for i in range(num + 1): - dc.DrawLine(bias + cell * i,bias,bias + cell * i,bias + width); - - #draw the outline of the board - dc.SetBrush(wx.BLACK_BRUSH); - dc.SetPen(wx.Pen(wx.BLACK,thick)); - dc.DrawRectangle(bias - margin,bias - margin,margin,width + margin * 2); - dc.DrawRectangle(bias - margin,bias - margin,width + margin * 2,margin); - dc.DrawRectangle(bias + width,bias - margin,margin,width + margin * 2); - dc.DrawRectangle(bias - margin,bias + width,width + margin * 2,margin); - - #draw coordinate labels - dc.SetTextForeground(wx.Colour(190,190,190)); - dc.SetFont( - wx.Font( - 12,wx.FONTFAMILY_SWISS,wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_BOLD,False,"Consolas" - ,wx.FONTENCODING_DEFAULT - ) - ); - for i in range(num): - dc.DrawText(chr(ord('A') + i),bias + cell / 2 + cell * i - 4,bias - margin / 2 - 10); - dc.DrawText(chr(ord('A') + i),bias + cell / 2 + cell * i - 4,bias + width + margin / 2 - 12); - dc.DrawText(chr(ord('1') + i),bias - margin / 2 - 4,bias + cell / 2 + cell * i - 10); - dc.DrawText(chr(ord('1') + i),bias + width + margin / 2 - 5,bias + cell / 2 + cell * i - 10); - - #draw stones - for i in range(num): - for j in range(num): - chssmn = self.brd.get(i + (j << 3)); - if chssmn == rv.black: - dc.SetBrush(wx.Brush(wx.Colour(40,40,40))); - dc.SetPen(wx.Pen(wx.Colour(20,20,20),thick)); - dc.DrawCircle(wx.Point(cbias + cell * i,cbias + cell * j),radius); - elif chssmn == reversi.white: - dc.SetBrush(wx.Brush(wx.Colour(210,210,210))); - dc.SetPen(wx.Pen(wx.Colour(230,230,230),thick)); - dc.DrawCircle(wx.Point(cbias + cell * i,cbias + cell * j),radius); - - #show where is the last move - if self.pos.check(): - if self.get(self.pos.x,self.pos.y) == rv.black: - dc.SetBrush(wx.Brush(wx.Colour(50,50,30))); - dc.SetPen(wx.Pen(wx.Colour(90,90,0),thick)); - else: - dc.SetBrush(wx.Brush(wx.Colour(210,210,170))); - dc.SetPen(wx.Pen(wx.Colour(200,200,30),thick)); - dc.DrawCircle(wx.Point(cbias + cell * self.pos.x,cbias + cell * self.pos.y),radius); - - def get_choice(self,mthd,color,depth): - p_mthd = rv.game.process_method(self,mthd,depth); - choices = self.brd.get_choice(p_mthd.first,color,p_mthd.second); - - self.dc.SetTextForeground(wx.Colour(255,30,30)); - self.dc.SetFont( - wx.Font( - 9,wx.FONTFAMILY_SWISS,wx.FONTSTYLE_NORMAL, - wx.FONTWEIGHT_BOLD,False,"Consolas", - wx.FONTENCODING_DEFAULT - ) - ); - for c in choices: - x = c.pos & 7; - y = c.pos >> 3; - str = "%.3f" % c.val; - self.dc.DrawText( - str, - bias + cell * x + cell / 2 - 3.5 * len(str), - bias + cell * y + cell / 2 - 8 - ); - - return choices; - - def print_log(self,str): - self.text_log.AppendText(str); - - def play_other(self,mthd,color,depth): - - p = sp.Popen(self.get_ply(color).path,stdin=sp.PIPE,stdout=sp.PIPE); - - s = ""; - result = rv.coordinate(); - request = { - "request":{ - "color":color, - "board":{ - "black":self.brd.bget(True), - "white":self.brd.bget(False) - } - } - }; - - s = json.dumps(request); - - self.text_log.AppendText( - "send a request to process \"" - + self.get_ply(color).path - + "\"\n" - ); - - self.text_log.AppendText(s + "\n"); - [s,str_err] = p.communicate(s.encode()); - self.text_log.AppendText( - "receive a response from process \"" - + self.get_ply(color).path - + "\"\n" - ); - self.text_log.AppendText(s.decode()); - response = json.loads(s.decode()); - - result.x = response["response"]["x"]; - result.y = response["response"]["y"]; - - self.flip(color,result.x,result.y); - - return result; - -reversi.board.config(); -mygame = game_gui(); -mygame.flag_print_term = False; \ No newline at end of file diff --git a/python/sample.py b/python/sample.py new file mode 100644 index 0000000..19af36b --- /dev/null +++ b/python/sample.py @@ -0,0 +1,120 @@ +import numpy as np; +import pickle; +import json; +import zipfile; +import os; +import signal; +import pysigset; + +import reversi as rv; +rv.board.config(); + +data_path = "../data/"; + +def extract_sample(filename): + result_pack = []; + + package = zipfile.ZipFile(data_path + filename); + color = None; + + for name in package.namelist(): + record = {}; + + package.extract(name, data_path); + with open(data_path + name, "r") as fobj: + lines = fobj.readlines(); + os.remove(data_path + name); + + for line in lines: + data = json.loads(line); + + assert("log" in data); + log = data["log"]; + brd = rv.board(); + brd.initial(); + + for turn_id in range(len(log)): + + try: + turn = log[turn_id]; + if "0" in turn: + color = True; + elif "1" in turn: + color = False; + else: + continue; + + assert(turn_id + 1 < len(log)); + turn_next = log[turn_id + 1]; + if "output" in turn_next and "display" in turn_next["output"] and "err" in turn_next["output"]["display"]: + break; + + turn = turn["0" if color else "1"].copy(); + assert("verdict" in turn); + if turn["verdict"] != "OK": + break; + assert("response" in turn); + turn = turn["response"]; + assert("x" in turn and "y" in turn); + if turn["x"] < 0 or turn["y"] < 0: + continue; + pos = turn["x"] + (turn["y"] << 3); + brd.flip(color, pos); + element = (brd.bget(color), brd.bget(not color)); + if element in record: + record[element] += 1; + else: + record[element] = 1; + except: + print(turn); + print(log); + print(name); + assert(False); + + result = np.empty((len(record), 4), dtype = np.uint64); + count = 0; + for i, j in record.items(): + result[count, :2] = i; + result[count, 2] = j; + count += 1; + + result_pack.append(result); + print("finish " + name) + + with open(data_path + filename[:-4] + ".dat", "wb") as fobj: + pickle.dump(result_pack, fobj); + +flag_int = False; +def on_interrupt(signum, frame): + global flag_int; + flag_int = True; + +def generate_label(sample): + assert(os.path.exists(data_path + sample)); + with open(data_path + sample, "rb") as fobj: + sample = np.load(fobj); + + if not os.path.exists(data_path + "label.dat"): + label = np.zeros(sample.shape[0]); + with open(data_path + "label.dat", "wb") as fobj: + pickle.dump([0, label], fobj); + + with open(data_path + "label.dat", "rb") as fobj: + [num, label] = pickle.load(fobj); + + brd = rv.board(); + handler_save = signal.signal(signal.SIGINT, on_interrupt); + for i in range(num, sample.shape[0]): + brd.assign(int(sample[i, 0]), int(sample[i, 1])); + label[i] = brd.search(True, 4); + if i % 1000 == 0: + print("finish", i) + if flag_int: + break; + + with open(data_path + "label.dat", "wb") as fobj: + pickle.dump([i, label], fobj); + signal.signal(signal.SIGINT, handler_save); + +extract_sample("Reversi-2018-2.zip"); +#generate_label("sample-2018-2.dat"); diff --git a/python/setup.py b/python/setup.py deleted file mode 100644 index d3aa8ff..0000000 --- a/python/setup.py +++ /dev/null @@ -1,22 +0,0 @@ -from distutils.core import setup, Extension - -src_dir = "../"; -src = ["type.cc","reversi.cc","flip.cc","search.cc","pattern.cc","tree.cc"]; -src = [src_dir + x for x in src]; -src += ["reversi_wrap.cxx"]; - -reversi_module = Extension( - "_reversi", - src, - define_macros=[("_hypot", "hypot"),("MS_WIN64", None)], - extra_compile_args=["-Ofast"], -); - -setup( - name = "reversi", - version = "0.1", - author = "Rick Lee", - description = "\"Simple reversi game\"", - ext_modules = [reversi_module], - py_modules = ["reversi"], -) \ No newline at end of file diff --git a/python/view_log.py b/python/view_log.py new file mode 100644 index 0000000..4cda579 --- /dev/null +++ b/python/view_log.py @@ -0,0 +1,40 @@ +import reversi as rv; + +class empty: + pass; + +def load_node(fobj): + ptr = empty(); + brd_white = int.from_bytes(fobj.read(8), "little"); + brd_black = int.from_bytes(fobj.read(8), "little"); + ptr.brd = rv.board(brd_black, brd_white); + ptr.color = int.from_bytes(fobj.read(1), "little"); + fobj.read(1); + ptr.height = int.from_bytes(fobj.read(2), "little"); + ptr.depth = int.from_bytes(fobj.read(2), "little"); + fobj.read(2); + ptr.alpha = rv.int2float(int.from_bytes(fobj.read(4), "little")); + ptr.beta = rv.int2float(int.from_bytes(fobj.read(4), "little")); + ptr.result = rv.int2float(int.from_bytes(fobj.read(4), "little")); + fobj.read(4); + ptr.child = []; + return ptr; + +def load_log(filename): + log = empty(); + table = [None for i in range(64)]; + + with open(filename, "rb") as fobj: + log.root = empty(); + log.root.child = []; + table[0] = log.root; + while fobj.peek(): + try: + ptr = load_node(fobj); + table[ptr.height].child.append(ptr); + ptr.parent = table[ptr.height]; + table[ptr.height + 1] = ptr; + except: + print(ptr.height, ptr.depth, ptr.alpha, ptr.beta, ptr.result); + break; + return log; diff --git a/python/wxs2xrc.py b/python/wxs2xrc.py deleted file mode 100644 index ba46571..0000000 --- a/python/wxs2xrc.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- - -import re -import codecs - -def wxs2xrc(wxsfile,xrcfile): - fobj = codecs.open(wxsfile,"r","UTF-8"); - lines = fobj.readlines(); - fobj.close(); - - lines_parse = []; - count = 0; - for line in lines: - if re.match(r".*wxFileDialog",line) != None: - count = 4; - if count > 0: - count -= 1; - continue; - lines_parse += re.sub(r"wxsmith",r"resource",line) - - fobj = codecs.open(xrcfile,"w","UTF-8"); - fobj.writelines(lines_parse); - fobj.close(); \ No newline at end of file diff --git a/resource.rc b/resource.rc deleted file mode 100644 index 24531d1..0000000 --- a/resource.rc +++ /dev/null @@ -1,3 +0,0 @@ -aaaa ICON "wx/msw/std.ico" - -#include "wx/msw/wx.rc" diff --git a/reversi.cbp b/reversi.cbp deleted file mode 100644 index 01471b1..0000000 --- a/reversi.cbp +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - diff --git a/reversi.cc b/reversi.cc deleted file mode 100644 index 8f373bc..0000000 --- a/reversi.cc +++ /dev/null @@ -1,127 +0,0 @@ -#include -#include -#include -#include -#include - -#include "reversi.h" -#include "search.h" - -const pos_type board::size; -const pos_type board::size2; -const pos_type board::pos_num; -const pos_type board::stage_num; -const short board::max_height; -bool board::flag_unicode = true; -brd_type board::node_count; - -#ifdef USE_FLOAT - const calc_type board::mark_max = 2; -#endif - -calc_type board::table_param[stage_num][board::pos_num] = { - {12,0.5,-6,-0.2}, - {10,0.5,-5,0.2}, - {3,1,0,0} -}; - -unordered_map trans_black; -unordered_map trans_white; - -void board::print(ostream& out)const{ - if(flag_unicode){ - string s = - "╔═╤═╤═╤═╤═╤═╤═╤═╗\n" - "║ │ │ │ │ │ │ │ ║\n" - "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" - "║ │ │ │ │ │ │ │ ║\n" - "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" - "║ │ │ │ │ │ │ │ ║\n" - "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" - "║ │ │ │ │ │ │ │ ║\n" - "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" - "║ │ │ │ │ │ │ │ ║\n" - "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" - "║ │ │ │ │ │ │ │ ║\n" - "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" - "║ │ │ │ │ │ │ │ ║\n" - "╟─┼─┼─┼─┼─┼─┼─┼─╢\n" - "║ │ │ │ │ │ │ │ ║\n" - "╚═╧═╧═╧═╧═╧═╧═╧═╝\n" - ; - - pos_type pos = 0; - for(char& chr:s){ - if(chr == ' '){ - switch(get(pos)){ - case blank: - out << " "; - break; - case black: - out << "●"; - break; - case white: - out << "○"; - break; - case null: - out << "╳"; - break; - default: - out << "╳"; - break; - } - ++pos; - }else{ - out << chr; - } - } - }else{ - const char chr_print[4] = {'.','O','#','*'}; - for(pos_type i = 0;i != size;++i){ - for(pos_type j = 0;j != size;++j){ - out << chr_print[get((i << 3) | j)]; - } - out << '\n'; - } - } -} - -choice board::select_choice(vector choices,const float& variation){ - - normal_distribution scatter(0,variation); - - for(choice& c:choices){ - c.rnd_val = c.val + scatter(engine); - } - - return *max_element( - choices.begin(),choices.end(), - [](const choice& c1,const choice& c2) -> bool{ - return c1.rnd_val < c2.rnd_val; - } - ); -} - -coordinate board::play(cmethod mthd,cbool color,cshort depth){ - - vector choices = get_choice(mthd,color,depth); - if(choices.empty()){ - return coordinate(-1,-1); - }else{ - choice best; - if(mthd == mthd_rnd){ - uniform_int_distribution scatter(0,choices.size() - 1); - best = choices[scatter(engine)]; - }else{ - float variation; - if(mthd & mthd_ptn){ - variation = 0.2; - }else{ - variation = 0.75; - } - best = select_choice(choices,variation); - } - flip(color,best.pos); - return coordinate(best.pos); - } -} diff --git a/reversi_gui.cbp b/reversi_gui.cbp deleted file mode 100644 index eff5819..0000000 --- a/reversi_gui.cbp +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - diff --git a/reversi_gui.cc b/reversi_gui.cc deleted file mode 100644 index ccafade..0000000 --- a/reversi_gui.cc +++ /dev/null @@ -1,250 +0,0 @@ -#include "reversi_gui.h" - -wxFrame* ptr_frame; -wxPanel* ptr_panel; -wxTextCtrl* ptr_term; -wxTextCtrl* ptr_log; -wxTextCtrl* ptr_input; -wxTreeCtrl* ptr_book; - -void show_choice(const vector& choices){ - wxClientDC dc(ptr_panel); - dc.SetTextForeground(wxColor(255,30,30)); - dc.SetFont( - wxFont( - 9,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL, - wxFONTWEIGHT_BOLD,false,_T("Consolas"), - wxFONTENCODING_DEFAULT - ) - ); - wxString str; - pos_type x,y; - for(const choice& c:choices){ - x = c.pos & 7; - y = c.pos >> 3; - str = wxString::FromDouble(c.val,3); - dc.DrawText(str,bias + cell * x + cell / 2 - 3.5 * str.size(),bias + cell * y + cell / 2 - 8); - } -} - -void do_show(wxDC& dc){ - - dc.Clear(); - - //draw valid moves - dc.SetBrush(wxBrush(wxColor(30,100,0))); - dc.SetPen(wxPen(wxColor(30,100,0),thick)); - brd_type brd_move = mygame.brd.get_move(mygame.color); - for(int i = 0;i != board::size2;++i){ - if(brd_move & (1ull << i)) - dc.DrawRectangle(bias + cell * (i & 7),bias + cell * (i >> 3),cell,cell); - } - - //draw a board - dc.SetPen(wxPen(*wxBLACK,thick)); - for(int i = 0;i != num + 1;++i){ - dc.DrawLine(bias,bias + cell * i,bias + width,bias + cell * i); - } - for(int i = 0;i != num + 1;++i){ - dc.DrawLine(bias + cell * i,bias,bias + cell * i,bias + width); - } - - //draw the outline of the board - dc.SetBrush(*wxBLACK); - dc.SetPen(wxPen(*wxBLACK,thick)); - dc.DrawRectangle(bias - margin,bias - margin,margin,width + margin * 2); - dc.DrawRectangle(bias - margin,bias - margin,width + margin * 2,margin); - dc.DrawRectangle(bias + width,bias - margin,margin,width + margin * 2); - dc.DrawRectangle(bias - margin,bias + width,width + margin * 2,margin); - - //draw coordinate labels - dc.SetTextForeground(wxColor(190,190,190)); - dc.SetFont( - wxFont( - 12,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL, - wxFONTWEIGHT_BOLD,false,_T("Consolas") - ,wxFONTENCODING_DEFAULT - ) - ); - for(int i = 0;i != num;++i){ - dc.DrawText(char('A' + i),bias + cell / 2 + cell * i - 4,bias - margin / 2 - 10); - dc.DrawText(char('A' + i),bias + cell / 2 + cell * i - 4,bias + width + margin / 2 - 12); - dc.DrawText(char('1' + i),bias - margin / 2 - 4,bias + cell / 2 + cell * i - 10); - dc.DrawText(char('1' + i),bias + width + margin / 2 - 5,bias + cell / 2 + cell * i - 10); - } - - //draw stones - chessman chssmn; - for(int i = 0;i != num;++i){ - for(int j = 0;j != num;++j){ - chssmn = mygame.brd.get(i + (j << 3)); - if(chssmn == black){ - dc.SetBrush(wxBrush(wxColor(40,40,40))); - dc.SetPen(wxPen(wxColor(20,20,20),thick)); - dc.DrawCircle(wxPoint(cbias + cell * i,cbias + cell * j),radius); - }else if(chssmn == white){ - dc.SetBrush(wxBrush(wxColor(210,210,210))); - dc.SetPen(wxPen(wxColor(230,230,230),thick)); - dc.DrawCircle(wxPoint(cbias + cell * i,cbias + cell * j),radius); - } - } - } - - //show where is the last move - if(mygame.pos.check()){ - if(mygame.get(mygame.pos.x,mygame.pos.y) == black){ - dc.SetBrush(wxBrush(wxColor(50,50,30))); - dc.SetPen(wxPen(wxColor(90,90,0),thick)); - }else{ - dc.SetBrush(wxBrush(wxColor(210,210,170))); - dc.SetPen(wxPen(wxColor(200,200,30),thick)); - } - dc.DrawCircle(wxPoint(cbias + cell * mygame.pos.x,cbias + cell * mygame.pos.y),radius); - } - -// int shrink = 14; -// -// //draw frontier -// dc.SetBrush(*wxTRANSPARENT_BRUSH); -// dc.SetPen(wxPen(wxColor(210,0,0),thick)); -// brd_type brd_front = board::get_front(mygame.bget(true) | mygame.bget(false)); -// for(int i = 0;i != board::size2;++i){ -// if(brd_front & (1ull << i)){ -// dc.DrawLine( -// bias + cell * (i & 7) + shrink, bias + cell * (i >> 3) + shrink, -// bias + cell * (i & 7) + cell - shrink, bias + cell * (i >> 3) + cell - shrink -// ); -// dc.DrawLine( -// bias + cell * (i & 7) + shrink, bias + cell * (i >> 3) + cell - shrink, -// bias + cell * (i & 7) + cell - shrink, bias + cell * (i >> 3) + shrink -// ); -// } -// } -// -// //draw stable stones -// dc.SetBrush(*wxTRANSPARENT_BRUSH); -// dc.SetPen(wxPen(wxColor(0,0,210),thick)); -// brd_type brd_stable = board::get_stable(mygame.bget(true) | mygame.bget(false)); -// for(int i = 0;i != board::size2;++i){ -// if(brd_stable & (1ull << i)){ -// dc.DrawLine( -// bias + cell * (i & 7) + shrink, bias + cell * (i >> 3) + shrink, -// bias + cell * (i & 7) + cell - shrink, bias + cell * (i >> 3) + cell - shrink -// ); -// dc.DrawLine( -// bias + cell * (i & 7) + shrink, bias + cell * (i >> 3) + cell - shrink, -// bias + cell * (i & 7) + cell - shrink, bias + cell * (i >> 3) + shrink -// ); -// } -// } -} - -void game_gui::show(){ - wxClientDC dc(ptr_panel); - do_show(dc); - wxYield(); -} - -void load_book(const string& path){ - book.load(path); - ptr_book->DeleteAllItems(); - wxTreeItemId item_root = ptr_book->AddRoot(_("Root")); - load_node(item_root,book.root); -} - -void load_node(const wxTreeItemId& item, node* ptr){ - wxTreeItemId item_branch; - ostringstream out; - - for(ptr = ptr->child;ptr;ptr = ptr->sibling){ - out << "x:" << (ptr->dat.pos & 7) << " y:" << (ptr->dat.pos >> 3) - << " " << (ptr->dat.color ? "black" : "white") - << " win:" << ptr->dat.win - << " lose:" << ptr->dat.lose; - item_branch = ptr_book->AppendItem(item,out.str(),-1,-1,new myTreeItemData(ptr)); - out.str(""); - load_node(item_branch,ptr); - } -} - -void quit(){ - ptr_frame->Destroy(); -} - -void print_term(const string& str){ - ptr_term->AppendText(str + "\n"); -} - -void print_log(const string& str){ - ptr_log->AppendText(str); -} - -void print_status(const string& str){ - ptr_frame->GetStatusBar()->SetStatusText(str,0); -} - -void load_script(const string& path){ - if(wxFileExists(path)){ - ptr_log->AppendText(_("open the file \"") + path + "\"\n"); - wxTextFile fileopen(path); - fileopen.Open(wxConvLocal); - wxString str; - for(str = fileopen.GetFirstLine();!fileopen.Eof();str += fileopen.GetNextLine()){ - str += _("\n"); - }; - process(str.ToStdString()); - fileopen.Close(); - }else{ - ptr_term->AppendText(_("cannot find the file \"") + path + "\"\n"); - } -} - -#include "jsoncpp/json.h" - -string path[2]; -long pid[2]; -wxProcess proc[2]; - -coordinate game_gui::play_other(cmethod mthd,cbool color,cshort depth){ - if(path[color] == get_ply(color).path){ - if(pid[color] == 0){ - proc[color].Redirect(); - pid[color] = wxExecute(path[color],wxEXEC_ASYNC,&proc[color]); - } - }else{ - path[color] = get_ply(color).path; - if(pid[color]){ - wxProcess::Kill(pid[color]); - } - - proc[color].Redirect(); - pid[color] = wxExecute(path[color],wxEXEC_ASYNC,&proc[color]); - } - - Json::Reader reader; - Json::Value request, response; - Json::FastWriter writer; - wxString str; - wxTextInputStream proc_in(*proc[color].GetInputStream()); - wxTextOutputStream proc_out(*proc[color].GetOutputStream()); - coordinate result; - - request["request"]["color"] = color; - request["request"]["board"]["black"] = brd.bget(true); - request["request"]["board"]["white"] = brd.bget(false); - - str = writer.write(request); - proc_out << str; - ptr_log->AppendText("send a request to process \"" + path[color] + "\"\n"); - ptr_log->AppendText(str); - str = proc_in.ReadLine(); - ptr_log->AppendText("receive a response from process \"" + path[color] + "\"\n"); - ptr_log->AppendText(str + "\n"); - reader.parse(str.ToStdString(),response); - result.x = response["response"]["x"].asInt(); - result.y = response["response"]["y"].asInt(); - - flip(color,result.x,result.y); - - return result; -} diff --git a/reversi_gui.cscope_file_list b/reversi_gui.cscope_file_list deleted file mode 100644 index 564151c..0000000 --- a/reversi_gui.cscope_file_list +++ /dev/null @@ -1,17 +0,0 @@ -"E:\LLK\ComputerSci\Cplusplus\reversi\flip.cc" -"E:\LLK\ComputerSci\Cplusplus\reversi\game.h" -"E:\LLK\ComputerSci\Cplusplus\reversi\search.cc" -"E:\LLK\ComputerSci\Cplusplus\reversi\wxsmith\reversi_guiframe.wxs" -"E:\LLK\ComputerSci\Cplusplus\reversi\tree.cc" -"E:\LLK\ComputerSci\Cplusplus\reversi\resource.rc" -"E:\LLK\ComputerSci\Cplusplus\reversi\reversi_gui.cc" -"E:\LLK\ComputerSci\Cplusplus\reversi\reversi_guiMain.h" -"E:\LLK\ComputerSci\Cplusplus\reversi\pattern.cc" -"E:\LLK\ComputerSci\Cplusplus\reversi\reversi_guiMain.cpp" -"E:\LLK\ComputerSci\Cplusplus\reversi\reversi_guiApp.h" -"E:\LLK\ComputerSci\Cplusplus\reversi\reversi_guiApp.cpp" -"E:\LLK\ComputerSci\Cplusplus\reversi\cpptcl.cc" -"E:\LLK\ComputerSci\Cplusplus\reversi\pattern.h" -"E:\LLK\ComputerSci\Cplusplus\reversi\reversi.h" -"E:\LLK\ComputerSci\Cplusplus\reversi\reversi_gui.h" -"E:\LLK\ComputerSci\Cplusplus\reversi\reversi.cc" diff --git a/reversi_gui.h b/reversi_gui.h deleted file mode 100644 index 974360d..0000000 --- a/reversi_gui.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef REVERSI_GUI_H -#define REVERSI_GUI_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "reversi_tcl.h" - -//export -const int bias = 34; -const int num = 8; -const int cell = 44; -const int width = num * cell; -const int cbias = bias + cell / 2; -const int radius = cell / 2 - 4; -const int thick = 3; -const int margin = 20; - -//import -extern wxFrame* ptr_frame; -extern wxPanel* ptr_panel; -extern wxTextCtrl* ptr_term; -extern wxTextCtrl* ptr_log; -extern wxTextCtrl* ptr_input; -extern wxTreeCtrl* ptr_book; - -//export -class myTreeItemData: public wxTreeItemData{ -public: - myTreeItemData(node*const& _ptr): ptr(_ptr){} - node* ptr; -}; - -//export -void do_show(wxDC& dc); -void load_node(const wxTreeItemId& item, node* ptr); - -#endif //REVERSI_GUI_H diff --git a/reversi_guiApp.cpp b/reversi_guiApp.cpp deleted file mode 100644 index a30de53..0000000 --- a/reversi_guiApp.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************** - * Name: reversi_guiApp.cpp - * Purpose: Code for Application Class - * Author: Rick (1300012743@pku.edu.cn) - * Created: 2016-04-16 - * Copyright: Rick () - * License: - **************************************************************/ - -#include "reversi_guiApp.h" - -//(*AppHeaders -#include "reversi_guiMain.h" -#include -//*) - -IMPLEMENT_APP(reversi_guiApp); - -bool reversi_guiApp::OnInit() -{ - //(*AppInitialize - bool wxsOK = true; - wxInitAllImageHandlers(); - if ( wxsOK ) - { - reversi_guiFrame* Frame = new reversi_guiFrame(0); - Frame->Show(); - SetTopWindow(Frame); - } - //*) - return wxsOK; - -} diff --git a/reversi_guiApp.h b/reversi_guiApp.h deleted file mode 100644 index 55b9e51..0000000 --- a/reversi_guiApp.h +++ /dev/null @@ -1,21 +0,0 @@ -/*************************************************************** - * Name: reversi_guiApp.h - * Purpose: Defines Application Class - * Author: Rick (1300012743@pku.edu.cn) - * Created: 2016-04-16 - * Copyright: Rick () - * License: - **************************************************************/ - -#ifndef REVERSI_GUIAPP_H -#define REVERSI_GUIAPP_H - -#include - -class reversi_guiApp : public wxApp -{ - public: - virtual bool OnInit(); -}; - -#endif // REVERSI_GUIAPP_H diff --git a/reversi_guiMain.cpp b/reversi_guiMain.cpp deleted file mode 100644 index d096e7d..0000000 --- a/reversi_guiMain.cpp +++ /dev/null @@ -1,744 +0,0 @@ -/*************************************************************** - * Name: reversi_guiMain.cpp - * Purpose: Code for Application Frame - * Author: Rick (1300012743@pku.edu.cn) - * Created: 2016-04-16 - * Copyright: Rick () - * License: - **************************************************************/ - -#include - -#include "reversi_guiMain.h" -#include - -//(*InternalHeaders(reversi_guiFrame) -#include -#include -#include -#include -#include -#include -#include -//*) - -#include "reversi_gui.h" - -//helper functions -enum wxbuildinfoformat { - short_f, long_f }; - -wxString wxbuildinfo(wxbuildinfoformat format) -{ - wxString wxbuild(wxVERSION_STRING); - - if (format == long_f ) - { -#if defined(__WXMSW__) - wxbuild << _T("-Windows"); -#elif defined(__UNIX__) - wxbuild << _T("-Linux"); -#endif - -#if wxUSE_UNICODE - wxbuild << _T("-Unicode build"); -#else - wxbuild << _T("-ANSI build"); -#endif // wxUSE_UNICODE - } - - return wxbuild; -} - -//(*IdInit(reversi_guiFrame) -const long reversi_guiFrame::id_panel_board = wxNewId(); -const long reversi_guiFrame::id_text_label = wxNewId(); -const long reversi_guiFrame::id_label_black = wxNewId(); -const long reversi_guiFrame::id_choice_black = wxNewId(); -const long reversi_guiFrame::id_text_path_black = wxNewId(); -const long reversi_guiFrame::id_button_folder_black = wxNewId(); -const long reversi_guiFrame::id_label_white = wxNewId(); -const long reversi_guiFrame::id_choice_white = wxNewId(); -const long reversi_guiFrame::id_text_path_white = wxNewId(); -const long reversi_guiFrame::id_button_folder_white = wxNewId(); -const long reversi_guiFrame::id_button_start = wxNewId(); -const long reversi_guiFrame::id_panel_note = wxNewId(); -const long reversi_guiFrame::id_text_term = wxNewId(); -const long reversi_guiFrame::id_text_log = wxNewId(); -const long reversi_guiFrame::id_book_tree = wxNewId(); -const long reversi_guiFrame::id_notebook = wxNewId(); -const long reversi_guiFrame::id_text_input = wxNewId(); -const long reversi_guiFrame::id_panel_base = wxNewId(); -const long reversi_guiFrame::id_menu_new = wxNewId(); -const long reversi_guiFrame::id_menu_load = wxNewId(); -const long reversi_guiFrame::id_menu_save = wxNewId(); -const long reversi_guiFrame::id_menu_quit = wxNewId(); -const long reversi_guiFrame::id_menu_undo = wxNewId(); -const long reversi_guiFrame::id_menu_redo = wxNewId(); -const long reversi_guiFrame::id_menu_mirror_h = wxNewId(); -const long reversi_guiFrame::id_menu_mirror_v = wxNewId(); -const long reversi_guiFrame::id_menu_reflect = wxNewId(); -const long reversi_guiFrame::id_menu_rotate_r = wxNewId(); -const long reversi_guiFrame::id_menu_rotate_l = wxNewId(); -const long reversi_guiFrame::id_menu_reverse = wxNewId(); -const long reversi_guiFrame::id_menu_trans = wxNewId(); -const long reversi_guiFrame::id_menu_eval = wxNewId(); -const long reversi_guiFrame::id_menu_clear_log = wxNewId(); -const long reversi_guiFrame::id_menu_clear_term = wxNewId(); -const long reversi_guiFrame::id_menu_clear = wxNewId(); -const long reversi_guiFrame::id_menu_alg_rnd = wxNewId(); -const long reversi_guiFrame::id_menu_alg_ab = wxNewId(); -const long reversi_guiFrame::id_menu_alg_pvs = wxNewId(); -const long reversi_guiFrame::id_menu_alg_trans = wxNewId(); -const long reversi_guiFrame::id_menu_alg_kill = wxNewId(); -const long reversi_guiFrame::id_menu_alg_mtdf = wxNewId(); -const long reversi_guiFrame::id_menu_alg_ids = wxNewId(); -const long reversi_guiFrame::id_menu_alg_ptn = wxNewId(); -const long reversi_guiFrame::id_menu_alg_mpc = wxNewId(); -const long reversi_guiFrame::id_menu_alg = wxNewId(); -const long reversi_guiFrame::id_menu_level1 = wxNewId(); -const long reversi_guiFrame::id_menu_level2 = wxNewId(); -const long reversi_guiFrame::id_menu_level3 = wxNewId(); -const long reversi_guiFrame::id_menu_level4 = wxNewId(); -const long reversi_guiFrame::id_menu_level5 = wxNewId(); -const long reversi_guiFrame::id_menu_level6 = wxNewId(); -const long reversi_guiFrame::id_menu_level7 = wxNewId(); -const long reversi_guiFrame::id_menu_level8 = wxNewId(); -const long reversi_guiFrame::id_menu_level9 = wxNewId(); -const long reversi_guiFrame::id_menu_level10 = wxNewId(); -const long reversi_guiFrame::id_menu_level = wxNewId(); -const long reversi_guiFrame::id_menu_about = wxNewId(); -const long reversi_guiFrame::id_statusbar = wxNewId(); -//*) - -BEGIN_EVENT_TABLE(reversi_guiFrame,wxFrame) - //(*EventTable(reversi_guiFrame) - //*) -END_EVENT_TABLE() - -reversi_guiFrame::reversi_guiFrame(wxWindow* parent,wxWindowID id) -{ - //(*Initialize(reversi_guiFrame) - wxBoxSizer* BoxSizer3; - wxBoxSizer* BoxSizer4; - wxBoxSizer* BoxSizer5; - wxBoxSizer* BoxSizer6; - wxBoxSizer* BoxSizer7; - wxBoxSizer* BoxSizer8; - wxBoxSizer* BoxSizer9; - wxMenu* Menu2; - wxMenu* menu; - wxMenuBar* menubar; - wxMenuItem* menu_about; - wxMenuItem* menu_quit; - - Create(parent, wxID_ANY, _("Reversi"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("wxID_ANY")); - { - wxIcon FrameIcon; - FrameIcon.CopyFromBitmap(wxBitmap(wxImage(_T("image\\Reversi.bmp")))); - SetIcon(FrameIcon); - } - BoxSizer1 = new wxBoxSizer(wxHORIZONTAL); - panel_base = new wxPanel(this, id_panel_base, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("id_panel_base")); - panel_base->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BACKGROUND)); - BoxSizer2 = new wxBoxSizer(wxHORIZONTAL); - BoxSizer3 = new wxBoxSizer(wxVERTICAL); - panel_board = new wxPanel(panel_base, id_panel_board, wxDefaultPosition, wxSize(424,424), wxSUNKEN_BORDER|wxTAB_TRAVERSAL, _T("id_panel_board")); - panel_board->SetBackgroundColour(wxColour(43,155,0)); - BoxSizer3->Add(panel_board, 1, wxALL, 5); - BoxSizer2->Add(BoxSizer3, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - BoxSizer4 = new wxBoxSizer(wxVERTICAL); - text_label = new wxStaticText(panel_base, id_text_label, _("Reversi"), wxDefaultPosition, wxSize(154,51), 0, _T("id_text_label")); - text_label->SetForegroundColour(wxColour(200,200,200)); - wxFont text_labelFont(26,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Segoe Script"),wxFONTENCODING_DEFAULT); - text_label->SetFont(text_labelFont); - BoxSizer4->Add(text_label, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - notebook = new wxNotebook(panel_base, id_notebook, wxDefaultPosition, wxSize(448,296), 0, _T("id_notebook")); - wxFont notebookFont(12,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Consolas"),wxFONTENCODING_DEFAULT); - notebook->SetFont(notebookFont); - panel_note = new wxPanel(notebook, id_panel_note, wxDefaultPosition, wxSize(424,424), wxSUNKEN_BORDER|wxTAB_TRAVERSAL, _T("id_panel_note")); - panel_note->SetForegroundColour(wxColour(200,200,200)); - panel_note->SetBackgroundColour(wxColour(32,32,32)); - box_sizer_note = new wxBoxSizer(wxVERTICAL); - BoxSizer5 = new wxBoxSizer(wxHORIZONTAL); - label_black = new wxStaticText(panel_note, id_label_black, _("Black Player:"), wxDefaultPosition, wxSize(163,22), 0, _T("id_label_black")); - label_black->SetForegroundColour(wxColour(200,200,200)); - wxFont label_blackFont(14,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Consolas"),wxFONTENCODING_DEFAULT); - label_black->SetFont(label_blackFont); - BoxSizer5->Add(label_black, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - choice_black = new wxChoice(panel_note, id_choice_black, wxDefaultPosition, wxDefaultSize, 0, 0, 0, wxDefaultValidator, _T("id_choice_black")); - choice_black->SetSelection( choice_black->Append(_("Human")) ); - choice_black->Append(_("Computer")); - choice_black->Append(_("Other Program")); - choice_black->SetForegroundColour(wxColour(32,32,32)); - choice_black->SetBackgroundColour(wxColour(200,200,200)); - wxFont choice_blackFont(14,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Consolas"),wxFONTENCODING_DEFAULT); - choice_black->SetFont(choice_blackFont); - BoxSizer5->Add(choice_black, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - box_sizer_note->Add(BoxSizer5, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - BoxSizer6 = new wxBoxSizer(wxHORIZONTAL); - text_path_black = new wxTextCtrl(panel_note, id_text_path_black, _("Irius offline"), wxDefaultPosition, wxSize(332,30), wxTE_PROCESS_ENTER, wxDefaultValidator, _T("id_text_path_black")); - text_path_black->SetBackgroundColour(wxColour(200,200,200)); - wxFont text_path_blackFont(14,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Consolas"),wxFONTENCODING_DEFAULT); - text_path_black->SetFont(text_path_blackFont); - BoxSizer6->Add(text_path_black, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - button_folder_black = new wxBitmapButton(panel_note, id_button_folder_black, wxBitmap(wxImage(_T("image\\folder_small.png"))), wxDefaultPosition, wxSize(32,29), wxBU_AUTODRAW, wxDefaultValidator, _T("id_button_folder_black")); - button_folder_black->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BACKGROUND)); - BoxSizer6->Add(button_folder_black, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - box_sizer_note->Add(BoxSizer6, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - BoxSizer7 = new wxBoxSizer(wxHORIZONTAL); - label_white = new wxStaticText(panel_note, id_label_white, _("White Player:"), wxDefaultPosition, wxSize(163,22), 0, _T("id_label_white")); - label_white->SetForegroundColour(wxColour(200,200,200)); - wxFont label_whiteFont(14,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Consolas"),wxFONTENCODING_DEFAULT); - label_white->SetFont(label_whiteFont); - BoxSizer7->Add(label_white, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - choice_white = new wxChoice(panel_note, id_choice_white, wxDefaultPosition, wxDefaultSize, 0, 0, 0, wxDefaultValidator, _T("id_choice_white")); - choice_white->Append(_("Human")); - choice_white->SetSelection( choice_white->Append(_("Computer")) ); - choice_white->Append(_("Other Program")); - choice_white->SetForegroundColour(wxColour(32,32,32)); - choice_white->SetBackgroundColour(wxColour(200,200,200)); - wxFont choice_whiteFont(14,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Consolas"),wxFONTENCODING_DEFAULT); - choice_white->SetFont(choice_whiteFont); - BoxSizer7->Add(choice_white, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - box_sizer_note->Add(BoxSizer7, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - BoxSizer8 = new wxBoxSizer(wxHORIZONTAL); - text_path_white = new wxTextCtrl(panel_note, id_text_path_white, _("Irius offline"), wxDefaultPosition, wxSize(332,30), wxTE_PROCESS_ENTER, wxDefaultValidator, _T("id_text_path_white")); - text_path_white->SetBackgroundColour(wxColour(200,200,200)); - wxFont text_path_whiteFont(14,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Consolas"),wxFONTENCODING_DEFAULT); - text_path_white->SetFont(text_path_whiteFont); - BoxSizer8->Add(text_path_white, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - button_folder_white = new wxBitmapButton(panel_note, id_button_folder_white, wxBitmap(wxImage(_T("image\\folder_small.png"))), wxDefaultPosition, wxSize(32,29), wxBU_AUTODRAW, wxDefaultValidator, _T("id_button_folder_white")); - button_folder_white->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BACKGROUND)); - BoxSizer8->Add(button_folder_white, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - box_sizer_note->Add(BoxSizer8, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - BoxSizer9 = new wxBoxSizer(wxHORIZONTAL); - button_start = new wxButton(panel_note, id_button_start, _("Start a New Game"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("id_button_start")); - button_start->SetForegroundColour(wxColour(32,32,32)); - button_start->SetBackgroundColour(wxColour(200,200,200)); - wxFont button_startFont(14,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Consolas"),wxFONTENCODING_DEFAULT); - button_start->SetFont(button_startFont); - BoxSizer9->Add(button_start, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - box_sizer_note->Add(BoxSizer9, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); - panel_note->SetSizer(box_sizer_note); - Layout(); - text_term = new wxTextCtrl(notebook, id_text_term, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY, wxDefaultValidator, _T("id_text_term")); - text_term->SetForegroundColour(wxColour(200,200,200)); - text_term->SetBackgroundColour(wxColour(32,32,32)); - wxFont text_termFont(14,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Consolas"),wxFONTENCODING_DEFAULT); - text_term->SetFont(text_termFont); - text_log = new wxTextCtrl(notebook, id_text_log, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY, wxDefaultValidator, _T("id_text_log")); - text_log->SetForegroundColour(wxColour(200,200,200)); - text_log->SetBackgroundColour(wxColour(32,32,32)); - wxFont text_logFont(14,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Consolas"),wxFONTENCODING_DEFAULT); - text_log->SetFont(text_logFont); - book_tree = new wxTreeCtrl(notebook, id_book_tree, wxDefaultPosition, wxDefaultSize, wxTR_DEFAULT_STYLE, wxDefaultValidator, _T("id_book_tree")); - book_tree->SetForegroundColour(wxColour(200,200,200)); - book_tree->SetBackgroundColour(wxColour(32,32,32)); - wxFont book_treeFont(14,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Consolas"),wxFONTENCODING_DEFAULT); - book_tree->SetFont(book_treeFont); - notebook->AddPage(panel_note, _("interaction"), false); - notebook->AddPage(text_term, _("terminal"), false); - notebook->AddPage(text_log, _("log"), false); - notebook->AddPage(book_tree, _("book"), false); - BoxSizer4->Add(notebook, 1, wxALL|wxEXPAND, 5); - text_input = new wxTextCtrl(panel_base, id_text_input, wxEmptyString, wxDefaultPosition, wxSize(266,30), wxTE_PROCESS_ENTER|wxTE_PROCESS_TAB, wxDefaultValidator, _T("id_text_input")); - text_input->SetForegroundColour(wxColour(200,200,200)); - text_input->SetBackgroundColour(wxColour(32,32,32)); - wxFont text_inputFont(14,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Consolas"),wxFONTENCODING_DEFAULT); - text_input->SetFont(text_inputFont); - BoxSizer4->Add(text_input, 0, wxALL|wxEXPAND, 5); - BoxSizer2->Add(BoxSizer4, 1, wxALL|wxEXPAND, 5); - panel_base->SetSizer(BoxSizer2); - BoxSizer2->Fit(panel_base); - BoxSizer2->SetSizeHints(panel_base); - BoxSizer1->Add(panel_base, 1, wxALL|wxEXPAND, 5); - SetSizer(BoxSizer1); - menubar = new wxMenuBar(); - menu = new wxMenu(); - menu_new = new wxMenuItem(menu, id_menu_new, _("&New Game"), _("Start a new game."), wxITEM_NORMAL); - menu->Append(menu_new); - menu_load = new wxMenuItem(menu, id_menu_load, _("&Load\tCtrl-L"), _("Load and execute a script."), wxITEM_NORMAL); - menu->Append(menu_load); - menu_save = new wxMenuItem(menu, id_menu_save, _("&Save\tCtrl-S"), wxEmptyString, wxITEM_NORMAL); - menu->Append(menu_save); - menu_quit = new wxMenuItem(menu, id_menu_quit, _("&Quit\tAlt-F4"), _("Quit the application."), wxITEM_NORMAL); - menu->Append(menu_quit); - menubar->Append(menu, _("&File")); - menu_edit = new wxMenu(); - menu_undo = new wxMenuItem(menu_edit, id_menu_undo, _("&Undo\tCtrl-Z"), _("Undo the latest change."), wxITEM_NORMAL); - menu_edit->Append(menu_undo); - menu_redo = new wxMenuItem(menu_edit, id_menu_redo, _("&Redo\tCtrl-Y"), _("Redo the latest change."), wxITEM_NORMAL); - menu_edit->Append(menu_redo); - menu_trans = new wxMenu(); - menu_mirror_h = new wxMenuItem(menu_trans, id_menu_mirror_h, _("Mirror &Horizontally\tAlt+H"), wxEmptyString, wxITEM_NORMAL); - menu_trans->Append(menu_mirror_h); - menu_mirror_v = new wxMenuItem(menu_trans, id_menu_mirror_v, _("Mirror &Vertically\tAlt+V"), wxEmptyString, wxITEM_NORMAL); - menu_trans->Append(menu_mirror_v); - menu_reflect = new wxMenuItem(menu_trans, id_menu_reflect, _("&Reflect\tAlt+R"), wxEmptyString, wxITEM_NORMAL); - menu_trans->Append(menu_reflect); - menu_rotate_r = new wxMenuItem(menu_trans, id_menu_rotate_r, _("Rotate &Clockwise\tAlt+C"), wxEmptyString, wxITEM_NORMAL); - menu_trans->Append(menu_rotate_r); - menu_rotate_l = new wxMenuItem(menu_trans, id_menu_rotate_l, _("Rotate Coun&terclockwise\tAlt+T"), wxEmptyString, wxITEM_NORMAL); - menu_trans->Append(menu_rotate_l); - menu_reverse = new wxMenuItem(menu_trans, id_menu_reverse, _("Reverse\tAlt+S"), wxEmptyString, wxITEM_NORMAL); - menu_trans->Append(menu_reverse); - menu_edit->Append(id_menu_trans, _("&Transform"), menu_trans, wxEmptyString); - menu_eval = new wxMenuItem(menu_edit, id_menu_eval, _("&Evaluate\tCtrl+E"), wxEmptyString, wxITEM_NORMAL); - menu_edit->Append(menu_eval); - menu_clear = new wxMenu(); - menu_clear_log = new wxMenuItem(menu_clear, id_menu_clear_log, _("&Log"), wxEmptyString, wxITEM_NORMAL); - menu_clear->Append(menu_clear_log); - menu_clear_term = new wxMenuItem(menu_clear, id_menu_clear_term, _("&Terminal"), wxEmptyString, wxITEM_NORMAL); - menu_clear->Append(menu_clear_term); - menu_edit->Append(id_menu_clear, _("&Clear"), menu_clear, wxEmptyString); - menubar->Append(menu_edit, _("&Edit")); - menu_set = new wxMenu(); - menu_alg = new wxMenu(); - menu_alg_rnd = new wxMenuItem(menu_alg, id_menu_alg_rnd, _("&Random"), wxEmptyString, wxITEM_CHECK); - menu_alg->Append(menu_alg_rnd); - menu_alg->AppendSeparator(); - menu_alg_ab = new wxMenuItem(menu_alg, id_menu_alg_ab, _("&Alpha-Beta Pruning"), wxEmptyString, wxITEM_CHECK); - menu_alg->Append(menu_alg_ab); - menu_alg_ab->Check(true); - menu_alg_pvs = new wxMenuItem(menu_alg, id_menu_alg_pvs, _("Principal &Variation Search"), wxEmptyString, wxITEM_CHECK); - menu_alg->Append(menu_alg_pvs); - menu_alg_pvs->Check(true); - menu_alg_trans = new wxMenuItem(menu_alg, id_menu_alg_trans, _("&Transposition Table"), wxEmptyString, wxITEM_CHECK); - menu_alg->Append(menu_alg_trans); - menu_alg_trans->Check(true); - menu_alg_kill = new wxMenuItem(menu_alg, id_menu_alg_kill, _("&Killer Heuristic"), wxEmptyString, wxITEM_CHECK); - menu_alg->Append(menu_alg_kill); - menu_alg_kill->Check(true); - menu_alg_mtdf = new wxMenuItem(menu_alg, id_menu_alg_mtdf, _("&Memory-Enhanced Test Driver"), wxEmptyString, wxITEM_CHECK); - menu_alg->Append(menu_alg_mtdf); - menu_alg_mtdf->Check(true); - menu_alg_ids = new wxMenuItem(menu_alg, id_menu_alg_ids, _("&Iterative Deepening Search"), wxEmptyString, wxITEM_CHECK); - menu_alg->Append(menu_alg_ids); - menu_alg_ptn = new wxMenuItem(menu_alg, id_menu_alg_ptn, _("&Pattern"), wxEmptyString, wxITEM_CHECK); - menu_alg->Append(menu_alg_ptn); - menu_alg_ptn->Check(true); - menu_alg_mpc = new wxMenuItem(menu_alg, id_menu_alg_mpc, _("Multi-Probability &Cut"), wxEmptyString, wxITEM_CHECK); - menu_alg->Append(menu_alg_mpc); - menu_set->Append(id_menu_alg, _("&Algorithm"), menu_alg, wxEmptyString); - menu_level = new wxMenu(); - menu_level1 = new wxMenuItem(menu_level, id_menu_level1, _("Level 1"), wxEmptyString, wxITEM_CHECK); - menu_level->Append(menu_level1); - menu_level2 = new wxMenuItem(menu_level, id_menu_level2, _("Level 2"), wxEmptyString, wxITEM_CHECK); - menu_level->Append(menu_level2); - menu_level3 = new wxMenuItem(menu_level, id_menu_level3, _("Level 3"), wxEmptyString, wxITEM_CHECK); - menu_level->Append(menu_level3); - menu_level4 = new wxMenuItem(menu_level, id_menu_level4, _("Level 4"), wxEmptyString, wxITEM_CHECK); - menu_level->Append(menu_level4); - menu_level5 = new wxMenuItem(menu_level, id_menu_level5, _("Level 5"), wxEmptyString, wxITEM_CHECK); - menu_level->Append(menu_level5); - menu_level6 = new wxMenuItem(menu_level, id_menu_level6, _("Level 6"), wxEmptyString, wxITEM_CHECK); - menu_level->Append(menu_level6); - menu_level7 = new wxMenuItem(menu_level, id_menu_level7, _("Level 7"), wxEmptyString, wxITEM_CHECK); - menu_level->Append(menu_level7); - menu_level8 = new wxMenuItem(menu_level, id_menu_level8, _("Level 8"), wxEmptyString, wxITEM_CHECK); - menu_level->Append(menu_level8); - menu_level8->Check(true); - menu_level9 = new wxMenuItem(menu_level, id_menu_level9, _("Level 9"), wxEmptyString, wxITEM_CHECK); - menu_level->Append(menu_level9); - menu_level10 = new wxMenuItem(menu_level, id_menu_level10, _("Level 10"), wxEmptyString, wxITEM_CHECK); - menu_level->Append(menu_level10); - menu_set->Append(id_menu_level, _("&Level"), menu_level, wxEmptyString); - menubar->Append(menu_set, _("&Settings")); - Menu2 = new wxMenu(); - menu_about = new wxMenuItem(Menu2, id_menu_about, _("&About\tF1"), _("Show info about this application."), wxITEM_NORMAL); - Menu2->Append(menu_about); - menubar->Append(Menu2, _("&Help")); - SetMenuBar(menubar); - statusbar = new wxStatusBar(this, id_statusbar, 0, _T("id_statusbar")); - int __wxStatusBarWidths_1[1] = { -1 }; - int __wxStatusBarStyles_1[1] = { wxSB_NORMAL }; - statusbar->SetFieldsCount(1,__wxStatusBarWidths_1); - statusbar->SetStatusStyles(1,__wxStatusBarStyles_1); - SetStatusBar(statusbar); - BoxSizer1->Fit(this); - BoxSizer1->SetSizeHints(this); - - panel_board->Connect(wxEVT_PAINT,(wxObjectEventFunction)&reversi_guiFrame::on_panel_board_paint,0,this); - panel_board->Connect(wxEVT_LEFT_DOWN,(wxObjectEventFunction)&reversi_guiFrame::on_panel_board_leftdown,0,this); - Connect(id_choice_black,wxEVT_COMMAND_CHOICE_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_choice_player); - Connect(id_text_path_black,wxEVT_COMMAND_TEXT_ENTER,(wxObjectEventFunction)&reversi_guiFrame::on_text_path_enter); - Connect(id_button_folder_black,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&reversi_guiFrame::on_button_folder_click); - Connect(id_choice_white,wxEVT_COMMAND_CHOICE_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_choice_player); - Connect(id_text_path_white,wxEVT_COMMAND_TEXT_ENTER,(wxObjectEventFunction)&reversi_guiFrame::on_text_path_enter); - Connect(id_button_folder_white,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&reversi_guiFrame::on_button_folder_click); - Connect(id_button_start,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&reversi_guiFrame::on_start); - Connect(id_text_input,wxEVT_COMMAND_TEXT_ENTER,(wxObjectEventFunction)&reversi_guiFrame::on_text_input_textenter); - Connect(id_menu_new,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_start); - Connect(id_menu_load,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_load); - Connect(id_menu_quit,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::OnQuit); - Connect(id_menu_undo,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_undo); - Connect(id_menu_redo,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_redo); - Connect(id_menu_mirror_h,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_transform); - Connect(id_menu_mirror_v,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_transform); - Connect(id_menu_reflect,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_transform); - Connect(id_menu_rotate_r,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_transform); - Connect(id_menu_rotate_l,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_transform); - Connect(id_menu_reverse,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_transform); - Connect(id_menu_eval,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_eval); - Connect(id_menu_clear_term,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_clear_term); - Connect(id_menu_clear,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_clear_all); - Connect(id_menu_alg_rnd,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_alg); - Connect(id_menu_alg_ab,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_alg); - Connect(id_menu_alg_pvs,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_alg); - Connect(id_menu_alg_trans,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_alg); - Connect(id_menu_alg_kill,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_alg); - Connect(id_menu_alg_mtdf,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_alg); - Connect(id_menu_alg_ids,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_alg); - Connect(id_menu_alg_ptn,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_alg); - Connect(id_menu_alg_mpc,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_alg); - Connect(id_menu_level1,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_level); - Connect(id_menu_level2,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_level); - Connect(id_menu_level3,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_level); - Connect(id_menu_level4,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_level); - Connect(id_menu_level5,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_level); - Connect(id_menu_level6,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_level); - Connect(id_menu_level7,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_level); - Connect(id_menu_level8,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_level); - Connect(id_menu_level9,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_level); - Connect(id_menu_level10,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::on_menu_level); - Connect(id_menu_about,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&reversi_guiFrame::OnAbout); - //*) - - Connect(id_book_tree,wxEVT_COMMAND_TREE_ITEM_ACTIVATED,(wxObjectEventFunction)&reversi_guiFrame::on_tree_item_select); - panel_board->Connect(wxEVT_CONTEXT_MENU,wxContextMenuEventHandler(reversi_guiFrame::on_context_menu),NULL,this); - - ptr_frame = this; - ptr_panel = panel_board; - ptr_term = text_term; - ptr_input = text_input; - ptr_log = text_log; - ptr_book = book_tree; - mygame.flag_lock = true; - flag_echo = true; - - text_path_black->Hide(); - button_folder_black->Hide(); - text_path_white->Hide(); - button_folder_white->Hide(); - box_sizer_note->Layout(); - - #ifdef DEBUG_SEARCH - out.open("out.html"); - #endif -} - -reversi_guiFrame::~reversi_guiFrame() -{ - //(*Destroy(reversi_guiFrame) - //*) -} - -void reversi_guiFrame::OnQuit(wxCommandEvent& event) -{ - Close(); -} - -void reversi_guiFrame::OnAbout(wxCommandEvent& event) -{ - wxString msg = _("Reversi Game\nBy Rick\n1300012743@pku.edu.cn"); - wxMessageBox(msg, _("About")); -} - -void reversi_guiFrame::OnClose(wxCloseEvent& event) -{ - #ifdef DEBUG_SEARCH - out.close(); - #endif -} - -void reversi_guiFrame::on_panel_board_paint(wxPaintEvent& event) -{ - wxClientDC dc(panel_board); - do_show(dc); -} - -void reversi_guiFrame::on_start(wxCommandEvent& event){ - process("start"); -} - -void reversi_guiFrame::on_undo(wxCommandEvent& event){ - process("undo"); -} - -void reversi_guiFrame::on_redo(wxCommandEvent& event){ - process("redo"); -} - -void reversi_guiFrame::on_load(wxCommandEvent& event){ - wxFileDialog* dialog_load = new wxFileDialog( - this, _("Select file"), wxEmptyString, wxEmptyString, - _("*.tcl"), wxFD_DEFAULT_STYLE, wxDefaultPosition, - wxDefaultSize, _T("wxFileDialog") - ); - - if(dialog_load->ShowModal() == wxID_OK){ - string path = dialog_load->GetPath().ToStdString(); - string::size_type pos = 0; - while((pos = path.find("\\",pos + 2)) != path.npos){ - path.replace(pos,1,"\\\\"); - } - process(string("load ") + path); - } -} - -void reversi_guiFrame::on_transform(wxCommandEvent& event){ - long id = event.GetId(); - if(id == id_menu_rotate_r){ - process("rotate_r"); - }else if(id == id_menu_rotate_l){ - process("rotate_l"); - }else if(id == id_menu_mirror_h){ - process("mirror_h"); - }else if(id == id_menu_mirror_v){ - process("mirror_v"); - }else if(id == id_menu_reflect){ - process("reflect"); - }else if(id == id_menu_reverse){ - process("reverse"); - } -} - -void reversi_guiFrame::on_eval(wxCommandEvent& event){ - process( - ( - _("puts [get_choice [get_method] [get_color] [get_depth]]") - ).ToStdString() - ); -} - -void reversi_guiFrame::on_clear_log(wxCommandEvent& event){ - text_log->Clear(); -} - -void reversi_guiFrame::on_clear_term(wxCommandEvent& event){ - text_term->Clear(); -} - -void reversi_guiFrame::on_clear_all(wxCommandEvent& event){ - text_log->Clear(); - text_term->Clear(); -} - -void reversi_guiFrame::on_menu_alg(wxCommandEvent& event){ - long id = event.GetId(); - wxMenuItem* item = menu_alg->FindItem(id); - - if(id == id_menu_alg_rnd){ - if(menu_alg_rnd->IsChecked()){ - for(wxMenuItem* ptr:menu_alg->GetMenuItems()){ - if(ptr->IsCheckable()){ - ptr->Check(false); - } - } - process("set_method $mthd_rnd"); - } - menu_alg_rnd->Check(true); - }else{ - if(item->IsChecked()){ - item->Check(true); - menu_alg_rnd->Check(false); - - if(id == id_menu_alg_ab){ - process("set_method [expr [get_method] | $mthd_ab]"); - }else if(id == id_menu_alg_kill){ - process("set_method [expr [get_method] | $mthd_kill]"); - }else if(id == id_menu_alg_pvs){ - process("set_method [expr [get_method] | $mthd_pvs]"); - }else if(id == id_menu_alg_trans){ - process("set_method [expr [get_method] | $mthd_trans]"); - }else if(id == id_menu_alg_mtdf){ - process("set_method [expr [get_method] | $mthd_mtdf]"); - }else if(id == id_menu_alg_ids){ - process("set_method [expr [get_method] | $mthd_ids]"); - }else if(id == id_menu_alg_ptn){ - process("set_method [expr [get_method] | $mthd_ptn]"); - }else if(id == id_menu_alg_mpc){ - process("set_method [expr [get_method] | $mthd_mpc]"); - } - }else{ - bool flag = false; - for(wxMenuItem* ptr:menu_alg->GetMenuItems()){ - if(ptr->IsChecked()){ - flag = true; - } - } - if(!flag){ - menu_alg_rnd->Check(true); - } - - if(id == id_menu_alg_ab){ - process("set_method [expr [get_method] & ~ $mthd_ab]"); - }else if(id == id_menu_alg_kill){ - process("set_method [expr [get_method] & ~ $mthd_kill]"); - }else if(id == id_menu_alg_pvs){ - process("set_method [expr [get_method] & ~ $mthd_pvs]"); - }else if(id == id_menu_alg_trans){ - process("set_method [expr [get_method] & ~ $mthd_trans]"); - }else if(id == id_menu_alg_mtdf){ - process("set_method [expr [get_method] & ~ $mthd_mtdf]"); - }else if(id == id_menu_alg_ids){ - process("set_method [expr [get_method] & ~ $mthd_ids]"); - }else if(id == id_menu_alg_ptn){ - process("set_method [expr [get_method] & ~ $mthd_ptn]"); - }else if(id == id_menu_alg_mpc){ - process("set_method [expr [get_method] & ~ $mthd_mpc]"); - } - } - } -} - -void reversi_guiFrame::on_menu_level(wxCommandEvent& event){ - for(wxMenuItem* ptr:menu_level->GetMenuItems()){ - ptr->Check(false); - } - - int pos; - wxMenuItem* item = menu_level->FindChildItem(event.GetId(),(size_t*)&pos); - item->Check(true); - if(pos == 7){ - pos = -1; - }else if(pos == 8){ - pos = -2; - }else if(pos == 9){ - pos = -3; - } - process((_("set_depth ") + to_string(pos)).ToStdString()); -} - -void reversi_guiFrame::on_panel_board_leftdown(wxMouseEvent& event) -{ - if(mygame.flag_lock){ - return; - } - wxPoint pos = event.GetPosition(); - int x = pos.x < bias ? -1 : (pos.x - bias) / cell; - int y = pos.y < bias ? -1 : (pos.y - bias) / cell; - process( - ( - _("puts [plays ") + to_string(x) + " " - + to_string(y) + _("]") - ).ToStdString() - ); -} - -void reversi_guiFrame::on_text_input_textenter(wxCommandEvent& event) -{ - process(text_input->GetValue().ToStdString()); -} - -void reversi_guiFrame::on_context_menu(wxContextMenuEvent& event){ - //wxMenu* menu = new wxMenu(); - - //menu->Append(id_undo, _("&Undo")); -// menu->Append(wxID_REDO, _("&Redo")); -// menu->AppendSeparator(); -// menu->Append(wxID_CUT, _("Cu&t")); -// menu->Append(wxID_COPY, _("&Copy")); -// menu->Append(wxID_PASTE, _("&Paste")); -// menu->Append(wxID_CLEAR, _("&Delete")); -// menu->AppendSeparator(); -// menu->Append(wxID_SELECTALL, _("Select &All")); -// - //PopupMenu(menu); -} - -void reversi_guiFrame::on_tree_item_select(wxTreeEvent& event){ - wxTreeItemId item = event.GetItem(); - vector vec; - board brd; - - while(item != book_tree->GetRootItem()){ - vec.push_back(((myTreeItemData*)(book_tree->GetItemData(item)))->ptr); - item = book_tree->GetItemParent(item); - } - reverse(vec.begin(),vec.end()); - if(!vec.empty()){ - mygame.color = vec.back()->dat.color; - }else{ - mygame.color = true; - } - brd.initial(); - for(node *& ptr:vec){ - brd.flip(!ptr->dat.color,ptr->dat.pos); - } - mygame.brd = brd; - mygame.show(); -} - -void reversi_guiFrame::on_choice_player(wxCommandEvent& event){ - if(event.GetId() == id_choice_black){ - process("set_player 1 " + to_string(choice_black->GetCurrentSelection())); - - if(choice_black->GetCurrentSelection() == ply_other){ - text_path_black->Show(); - button_folder_black->Show(); - }else{ - text_path_black->Hide(); - button_folder_black->Hide(); - } - box_sizer_note->Layout(); - }else if(event.GetId() == id_choice_white){ - process("set_player 0 " + to_string(choice_white->GetCurrentSelection())); - - if(choice_white->GetCurrentSelection() == ply_other){ - text_path_white->Show(); - button_folder_white->Show(); - }else{ - text_path_white->Hide(); - button_folder_white->Hide(); - } - box_sizer_note->Layout(); - } -} - -void reversi_guiFrame::on_text_path_enter(wxCommandEvent& event) -{ - if(event.GetId() == id_text_path_black){ - process(string("set_player_path 1 \"") + text_path_black->GetValue().ToStdString() + "\""); - }else if(event.GetId() == id_text_path_white){ - process(string("set_player_path 0 \"") + text_path_white->GetValue().ToStdString() + "\""); - } -} - -void reversi_guiFrame::on_button_folder_click(wxCommandEvent& event) -{ - if(event.GetId() == id_button_folder_black){ - wxFileDialog* dialog_choice_player = new wxFileDialog( - this, _("Select file"), wxEmptyString, wxEmptyString, - _("*.exe"), wxFD_DEFAULT_STYLE, wxDefaultPosition, - wxDefaultSize, _T("wxFileDialog") - ); - - if(dialog_choice_player->ShowModal() == wxID_OK){ - string path = dialog_choice_player->GetPath().ToStdString(); - string::size_type pos = 0; - while((pos = path.find("\\",pos + 2)) != path.npos){ - path.replace(pos,1,"\\\\"); - } - text_path_black->SetValue(path); - process(string("set_player_path 1 \"") + path + "\""); - } - }else if(event.GetId() == id_button_folder_white){ - wxFileDialog* dialog_choice_player = new wxFileDialog( - this, _("Select file"), wxEmptyString, wxEmptyString, - _("*.exe"), wxFD_DEFAULT_STYLE, wxDefaultPosition, - wxDefaultSize, _T("wxFileDialog") - ); - - if(dialog_choice_player->ShowModal() == wxID_OK){ - string path = dialog_choice_player->GetPath().ToStdString(); - string::size_type pos = 0; - while((pos = path.find("\\",pos + 2)) != path.npos){ - path.replace(pos,1,"\\\\"); - } - text_path_white->SetValue(path); - process(string("set_player_path 0 \"") + path + "\""); - } - } -} diff --git a/reversi_guiMain.h b/reversi_guiMain.h deleted file mode 100644 index 292d17e..0000000 --- a/reversi_guiMain.h +++ /dev/null @@ -1,193 +0,0 @@ -/*************************************************************** - * Name: reversi_guiMain.h - * Purpose: Defines Application Frame - * Author: Rick (1300012743@pku.edu.cn) - * Created: 2016-04-16 - * Copyright: Rick () - * License: - **************************************************************/ - -#ifndef REVERSI_GUIMAIN_H -#define REVERSI_GUIMAIN_H - -//(*Headers(reversi_guiFrame) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//*) -#include -#include - -class reversi_guiFrame: public wxFrame -{ - public: - - reversi_guiFrame(wxWindow* parent,wxWindowID id = -1); - virtual ~reversi_guiFrame(); - - private: - - //(*Handlers(reversi_guiFrame) - void OnQuit(wxCommandEvent& event); - void OnAbout(wxCommandEvent& event); - void OnClose(wxCloseEvent& event); - void OnClose1(wxCloseEvent& event); - void on_panel_board_paint(wxPaintEvent& event); - void on_panel_board_leftdown(wxMouseEvent& event); - void on_text_input_textenter(wxCommandEvent& event); - void on_text_path_enter(wxCommandEvent& event); - void on_start(wxCommandEvent& event); - void on_button_folder_click(wxCommandEvent& event); - void on_choice_player(wxCommandEvent& event); - //*) - void on_undo(wxCommandEvent& event); - void on_redo(wxCommandEvent& event); - void on_load(wxCommandEvent& event); - void on_clear_log(wxCommandEvent& event); - void on_clear_term(wxCommandEvent& event); - void on_clear_all(wxCommandEvent& event); - void on_transform(wxCommandEvent& event); - void on_eval(wxCommandEvent& event); - void on_menu_alg(wxCommandEvent& event); - void on_menu_level(wxCommandEvent& event); - void on_context_menu(wxContextMenuEvent& event); - void on_tree_item_select(wxTreeEvent& event); - - //(*Identifiers(reversi_guiFrame) - static const long id_panel_board; - static const long id_text_label; - static const long id_label_black; - static const long id_choice_black; - static const long id_text_path_black; - static const long id_button_folder_black; - static const long id_label_white; - static const long id_choice_white; - static const long id_text_path_white; - static const long id_button_folder_white; - static const long id_button_start; - static const long id_panel_note; - static const long id_text_term; - static const long id_text_log; - static const long id_book_tree; - static const long id_notebook; - static const long id_text_input; - static const long id_panel_base; - static const long id_menu_new; - static const long id_menu_load; - static const long id_menu_save; - static const long id_menu_quit; - static const long id_menu_undo; - static const long id_menu_redo; - static const long id_menu_mirror_h; - static const long id_menu_mirror_v; - static const long id_menu_reflect; - static const long id_menu_rotate_r; - static const long id_menu_rotate_l; - static const long id_menu_reverse; - static const long id_menu_trans; - static const long id_menu_eval; - static const long id_menu_clear_log; - static const long id_menu_clear_term; - static const long id_menu_clear; - static const long id_menu_alg_rnd; - static const long id_menu_alg_ab; - static const long id_menu_alg_pvs; - static const long id_menu_alg_trans; - static const long id_menu_alg_kill; - static const long id_menu_alg_mtdf; - static const long id_menu_alg_ids; - static const long id_menu_alg_ptn; - static const long id_menu_alg_mpc; - static const long id_menu_alg; - static const long id_menu_level1; - static const long id_menu_level2; - static const long id_menu_level3; - static const long id_menu_level4; - static const long id_menu_level5; - static const long id_menu_level6; - static const long id_menu_level7; - static const long id_menu_level8; - static const long id_menu_level9; - static const long id_menu_level10; - static const long id_menu_level; - static const long id_menu_about; - static const long id_statusbar; - //*) - - //(*Declarations(reversi_guiFrame) - wxBitmapButton* button_folder_black; - wxBitmapButton* button_folder_white; - wxBoxSizer* BoxSizer1; - wxBoxSizer* BoxSizer2; - wxBoxSizer* box_sizer_note; - wxButton* button_start; - wxChoice* choice_black; - wxChoice* choice_white; - wxMenu* menu_alg; - wxMenu* menu_clear; - wxMenu* menu_edit; - wxMenu* menu_level; - wxMenu* menu_set; - wxMenu* menu_trans; - wxMenuItem* menu_alg_ab; - wxMenuItem* menu_alg_ids; - wxMenuItem* menu_alg_kill; - wxMenuItem* menu_alg_mpc; - wxMenuItem* menu_alg_mtdf; - wxMenuItem* menu_alg_ptn; - wxMenuItem* menu_alg_pvs; - wxMenuItem* menu_alg_rnd; - wxMenuItem* menu_alg_trans; - wxMenuItem* menu_clear_log; - wxMenuItem* menu_clear_term; - wxMenuItem* menu_eval; - wxMenuItem* menu_level10; - wxMenuItem* menu_level1; - wxMenuItem* menu_level2; - wxMenuItem* menu_level3; - wxMenuItem* menu_level4; - wxMenuItem* menu_level5; - wxMenuItem* menu_level6; - wxMenuItem* menu_level7; - wxMenuItem* menu_level8; - wxMenuItem* menu_level9; - wxMenuItem* menu_load; - wxMenuItem* menu_mirror_h; - wxMenuItem* menu_mirror_v; - wxMenuItem* menu_new; - wxMenuItem* menu_redo; - wxMenuItem* menu_reflect; - wxMenuItem* menu_reverse; - wxMenuItem* menu_rotate_l; - wxMenuItem* menu_rotate_r; - wxMenuItem* menu_save; - wxMenuItem* menu_undo; - wxNotebook* notebook; - wxPanel* panel_base; - wxPanel* panel_board; - wxPanel* panel_note; - wxStaticText* label_black; - wxStaticText* label_white; - wxStaticText* text_label; - wxStatusBar* statusbar; - wxTextCtrl* text_input; - wxTextCtrl* text_log; - wxTextCtrl* text_path_black; - wxTextCtrl* text_path_white; - wxTextCtrl* text_term; - wxTreeCtrl* book_tree; - //*) - - DECLARE_EVENT_TABLE() -}; - -#endif // REVERSI_GUIMAIN_H diff --git a/reversi_json.cbp b/reversi_json.cbp deleted file mode 100644 index a1ca27a..0000000 --- a/reversi_json.cbp +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - diff --git a/reversi_tcl.cc b/reversi_tcl.cc deleted file mode 100644 index 3cefd08..0000000 --- a/reversi_tcl.cc +++ /dev/null @@ -1,350 +0,0 @@ -#include -#include - -#include "cpptcl.h" -#include "reversi_tcl.h" - -using namespace Tcl; - -game_gui mygame; -tree book; -interpreter* ptr_inter; -bool flag_echo = false; - -void game_gui::print_log(const string& str){ - return ::print_log(str); -} - -object brd2obj(cboard brd){ - object result; - result.append(*ptr_inter,object((int)(brd.bget(true) >> 32))); - result.append(*ptr_inter,object((int)(brd.bget(true)))); - result.append(*ptr_inter,object((int)(brd.bget(false) >> 32))); - result.append(*ptr_inter,object((int)(brd.bget(false)))); - return result; -} - -board obj2brd(const object& obj){ - board brd; - brd_type brd_black,brd_white; - brd_black = (unsigned int)obj.at(*ptr_inter,0).get(*ptr_inter); - brd_black <<= 32; - brd_black |= (unsigned int)obj.at(*ptr_inter,1).get(*ptr_inter); - brd_white = (unsigned int)obj.at(*ptr_inter,2).get(*ptr_inter); - brd_white <<= 32; - brd_white |= (unsigned int)obj.at(*ptr_inter,3).get(*ptr_inter); - brd.assign(brd_black,brd_white); - return brd; -} - -object choice2obj(cchoice c){ - object result; - result.append(*ptr_inter,object(double(c.val))); - result.append(*ptr_inter,object(int(c.pos & 7))); - result.append(*ptr_inter,object(int(c.pos >> 3))); - return result; -} - -choice obj2choice(const object& obj){ - choice result; - result.val = obj.at(*ptr_inter,0).get(*ptr_inter); - result.pos = obj.at(*ptr_inter,1).get(*ptr_inter) - + (obj.at(*ptr_inter,2).get(*ptr_inter) << 3); - return result; -} - -template -object vec2obj(const vector& vec){ - object result; - for(const T& i:vec){ - result.append(*ptr_inter,object(i)); - } - return result; -} - -template<> -object vec2obj(const vector& vec){ - object result; - for(const object& i:vec){ - result.append(*ptr_inter,i); - } - return result; -} - -vector obj2vec(const object& objs){ - vector result; - object obj; - int num = objs.length(*ptr_inter); - for(int i = 0;i != num;++i){ - obj = objs.at(*ptr_inter,i); - result.push_back(obj); - } - return result; -} - -void start(){ - mygame.start(); -} - -void auto_save(cbool flag){ - mygame.flag_auto_save = flag; -} - -object bget(){ - return brd2obj(mygame.brd); -} - -void assign(const object& obj){ - board brd = obj2brd(obj); - mygame.assign(brd); -} - -int visit(cint x, cint y){ - return mygame.get(pos_type(x),pos_type(y)); -} - -void set(cint x, cint y, cint chsman){ - return mygame.set(pos_type(x),pos_type(y),chessman(chsman)); -} - -int count(cbool color){ - return mygame.count(color); -} - -int count_move(cbool color){ - return mygame.count_move(color); -} - -float score(cbool color){ - return mygame.score(color); -} - -void config(){ - pattern::config(); - mygame.config(); - grp.load("data/pattern.dat"); -} - -void set_player(cbool color,cint p_type){ - mygame.get_ply(color).p_type = player_type(p_type); -} - -void set_player_path(cbool color,const string& str){ - mygame.get_ply(color).path = str; -} - -bool flip(cbool color,cint x,cint y){ - return mygame.flip(color,x,y); -} - -object play(cint mthd,cbool color,cint height){ - auto pos = mygame.play(method(mthd),color,height); - object result; - result.append(*ptr_inter,object(int(pos.x))); - result.append(*ptr_inter,object(int(pos.y))); - return result; -} - -object plays(cint x,cint y){ - auto pos = mygame.play(coordinate(x,y)); - object result; - result.append(*ptr_inter,object(int(pos.x))); - result.append(*ptr_inter,object(int(pos.y))); - return result; -} - -bool undo(){ - return mygame.undo(); -} -bool redo(){ - return mygame.redo(); -} - -void mirror_h(){ - return mygame.mirror_h(); -} -void mirror_v(){ - return mygame.mirror_v(); -} -void reflect(){ - return mygame.reflect(); -} -void rotate_l(){ - return mygame.rotate_l(); -} -void rotate_r(){ - return mygame.rotate_r(); -} -void reverse(){ - return mygame.reverse(); -} - -bool get_color(){ - return mygame.color; -} -void set_color(cbool color){ - mygame.set_color(color); -} - -int get_method(){ - return mygame.mthd; -} -void set_method(cint mthd){ - mygame.mthd = method(mthd); -} - -int get_depth(){ - return mygame.depth; -} -void set_depth(cint depth){ - mygame.depth = depth; -} - -bool get_is_lock(){ - return mygame.flag_lock; -} -void set_is_lock(cbool flag_lock){ - mygame.flag_lock = flag_lock; -} - -object get_pos(){ - object result; - result.append(*ptr_inter,object(int(mygame.pos.x))); - result.append(*ptr_inter,object(int(mygame.pos.y))); - return result; -} -void set_pos(cint x,cint y){ - mygame.set_pos(x,y); -} - -object get_choice(cint mthd,cbool color,cint height){ - vector choices = mygame.get_choice(method(mthd),color,height); - show_choice(choices); - vector vec; - for(const choice& c:choices){ - vec.push_back(choice2obj(c)); - } - return vec2obj(vec); -} - -object select_choice(object objs){ - vector vec = obj2vec(objs); - vector choices; - for(const object& obj:vec){ - choices.push_back(obj2choice(obj)); - } - return choice2obj(mygame.select_choice(choices)); -} - -void load(const string& path){ - return book.load(path); -}; - -void grp_initial(cint size){ - return grp.initial(size); -} -void grp_load(const string& filename){ - return grp.load(filename); -} -void grp_save(const string& filename){ - return grp.save(filename); -} - -void process(const string& str){ - - static interpreter inter; - static bool flag = true; - - if(flag){ - flag = false; - ptr_inter = &inter; - - inter.def("quit",::quit); - inter.def("exit",::quit); - inter.def("puts",::print_term); - inter.def("print",::print_term); - - inter.def("start",::start); - inter.def("config",::config); - inter.def("flip",::flip); - inter.def("play",::play); - inter.def("plays",::plays); - inter.def("undo",::undo); - inter.def("redo",::redo); - inter.def("mirror_h",::mirror_h); - inter.def("mirror_v",::mirror_v); - inter.def("reflect",::reflect); - inter.def("rotate_l",::rotate_l); - inter.def("rotate_r",::rotate_r); - inter.def("reverse",::reverse); - inter.def("auto_save",::auto_save); - inter.def("bget",::bget); - inter.def("assign",::assign); - inter.def("visit",::visit); - inter.def("place",::set); - inter.def("get_color",::get_color); - inter.def("set_color",::set_color); - inter.def("get_method",::get_method); - inter.def("set_method",::set_method); - inter.def("get_depth",::get_depth); - inter.def("set_depth",::set_depth); - inter.def("get_pos",::get_pos); - inter.def("set_pos",::set_pos); - inter.def("set_player",::set_player); - inter.def("set_player_path",::set_player_path); - inter.def("get_is_lock",::get_is_lock); - inter.def("set_is_lock",::set_is_lock); - inter.def("get_choice",::get_choice); - inter.def("select_choice",::select_choice); - inter.def("count",::count); - inter.def("count_move",::count_move); - inter.def("score",::score); - - inter.def("load",::load); - - inter.def("grp_initial",::grp_initial); - inter.def("grp_load",::grp_load); - inter.def("grp_save",::grp_save); - - inter.def("load_book",::load_book); - - inter.eval( - "set blank 0;" - "set white 1;" - "set black 2;" - "set null 3;" - - "set false 0;" - "set true 1;" - - "set mthd_rnd 0x0;" - "set mthd_ab 0x1;" - "set mthd_kill 0x2;" - "set mthd_pvs 0x4;" - "set mthd_trans 0x8;" - "set mthd_mtdf 0x10;" - "set mthd_ids 0x20;" - "set mthd_ptn 0x40;" - "set mthd_mpc 0x80;" - "set mthd_end 0x100;" - - "config;" - ); - } - - if(flag_echo){ - print_term(string(">>") + str); - } - - try{ - chrono::system_clock::time_point time_start = chrono::system_clock::now(); - inter.eval(str); - chrono::system_clock::time_point time_end = chrono::system_clock::now(); - chrono::duration time_exec = time_end - time_start; - print_status( - "Execution time : " + to_string(time_exec.count()) + " seconds" - ); - }catch(const tcl_error& err){ - print_term(string(err.what())); - } -} \ No newline at end of file diff --git a/reversi_tcl.h b/reversi_tcl.h deleted file mode 100644 index bd66429..0000000 --- a/reversi_tcl.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef REVERSI_TCL_H -#define REVERSI_TCL_H - -#include "game.h" -#include "pattern.h" - -//import -class game_gui:public game{ -public: - virtual void show(); - virtual void print_log(const string&); - virtual coordinate play_other(cmethod mthd,cbool color,cshort depth = -1); -}; - -//export -void process(const string& str); - -//import -void quit(); -void print_term(const string& str); -void print_log(const string& str); -void print_status(const string& str); -void show_choice(const vector& choices); -void load_book(const string& path); - -//export -extern game_gui mygame; -extern tree book; -extern bool flag_echo; - -#endif //REVERSI_TCL_H \ No newline at end of file diff --git a/search.h b/search.h deleted file mode 100644 index f286f45..0000000 --- a/search.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef SEARCH_H -#define SEARCH_H - -typedef unordered_map trans_type; -extern calc_type table_val[board::size2 + 1][board::size2]; -extern const calc_type table_val_init[board::size2]; -extern trans_type table_trans[2]; - -#endif //SEARCH_H \ No newline at end of file diff --git a/single/jsoncpp.cpp b/single/jsoncpp.cpp deleted file mode 100644 index 260f19f..0000000 --- a/single/jsoncpp.cpp +++ /dev/null @@ -1,3686 +0,0 @@ -/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/). -/// It is intented to be used with #include - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is -released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur - -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. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - - -#include "jsoncpp/json.h" - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_tool.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED -#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED - -/* This header provides common string manipulation support, such as UTF-8, - * portable conversion from/to string... - * - * It is an internal header that must not be exposed. - */ - -namespace Json { - -/// Converts a unicode code-point to UTF-8. -static inline std::string codePointToUTF8(unsigned int cp) { - std::string result; - - // based on description from http://en.wikipedia.org/wiki/UTF-8 - - if (cp <= 0x7f) { - result.resize(1); - result[0] = static_cast(cp); - } else if (cp <= 0x7FF) { - result.resize(2); - result[1] = static_cast(0x80 | (0x3f & cp)); - result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); - } else if (cp <= 0xFFFF) { - result.resize(3); - result[2] = static_cast(0x80 | (0x3f & cp)); - result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); - result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); - } else if (cp <= 0x10FFFF) { - result.resize(4); - result[3] = static_cast(0x80 | (0x3f & cp)); - result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); - result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); - result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); - } - - return result; -} - -/// Returns true if ch is a control character (in range [0,32[). -static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } - -enum { - /// Constant that specify the size of the buffer that must be passed to - /// uintToString. - uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 -}; - -// Defines a char buffer for use with uintToString(). -typedef char UIntToStringBuffer[uintToStringBufferSize]; - -/** Converts an unsigned integer to string. - * @param value Unsigned interger to convert to string - * @param current Input/Output string buffer. - * Must have at least uintToStringBufferSize chars free. - */ -static inline void uintToString(LargestUInt value, char*& current) { - *--current = 0; - do { - *--current = char(value % 10) + '0'; - value /= 10; - } while (value != 0); -} - -/** Change ',' to '.' everywhere in buffer. - * - * We had a sophisticated way, but it did not work in WinCE. - * @see https://github.com/open-source-parsers/jsoncpp/pull/9 - */ -static inline void fixNumericLocale(char* begin, char* end) { - while (begin < end) { - if (*begin == ',') { - *begin = '.'; - } - ++begin; - } -} - -} // namespace Json { - -#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_tool.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_reader.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2011 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include "json_tool.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below -#define snprintf _snprintf -#endif - -#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 -// Disable warning about strdup being deprecated. -#pragma warning(disable : 4996) -#endif - -namespace Json { - -// Implementation of class Features -// //////////////////////////////// - -Features::Features() - : allowComments_(true), strictRoot_(false), - allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} - -Features Features::all() { return Features(); } - -Features Features::strictMode() { - Features features; - features.allowComments_ = false; - features.strictRoot_ = true; - features.allowDroppedNullPlaceholders_ = false; - features.allowNumericKeys_ = false; - return features; -} - -// Implementation of class Reader -// //////////////////////////////// - -static inline bool in(Reader::Char c, - Reader::Char c1, - Reader::Char c2, - Reader::Char c3, - Reader::Char c4) { - return c == c1 || c == c2 || c == c3 || c == c4; -} - -static inline bool in(Reader::Char c, - Reader::Char c1, - Reader::Char c2, - Reader::Char c3, - Reader::Char c4, - Reader::Char c5) { - return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; -} - -static bool containsNewLine(Reader::Location begin, Reader::Location end) { - for (; begin < end; ++begin) - if (*begin == '\n' || *begin == '\r') - return true; - return false; -} - -// Class Reader -// ////////////////////////////////////////////////////////////////// - -Reader::Reader() - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), features_(Features::all()), - collectComments_() {} - -Reader::Reader(const Features& features) - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), features_(features), collectComments_() { -} - -bool -Reader::parse(const std::string& document, Value& root, bool collectComments) { - document_ = document; - const char* begin = document_.c_str(); - const char* end = begin + document_.length(); - return parse(begin, end, root, collectComments); -} - -bool Reader::parse(std::istream& sin, Value& root, bool collectComments) { - // std::istream_iterator begin(sin); - // std::istream_iterator end; - // Those would allow streamed input from a file, if parse() were a - // template function. - - // Since std::string is reference-counted, this at least does not - // create an extra copy. - std::string doc; - std::getline(sin, doc, (char)EOF); - return parse(doc, root, collectComments); -} - -bool Reader::parse(const char* beginDoc, - const char* endDoc, - Value& root, - bool collectComments) { - if (!features_.allowComments_) { - collectComments = false; - } - - begin_ = beginDoc; - end_ = endDoc; - collectComments_ = collectComments; - current_ = begin_; - lastValueEnd_ = 0; - lastValue_ = 0; - commentsBefore_ = ""; - errors_.clear(); - while (!nodes_.empty()) - nodes_.pop(); - nodes_.push(&root); - - bool successful = readValue(); - Token token; - skipCommentTokens(token); - if (collectComments_ && !commentsBefore_.empty()) - root.setComment(commentsBefore_, commentAfter); - if (features_.strictRoot_) { - if (!root.isArray() && !root.isObject()) { - // Set error location to start of doc, ideally should be first token found - // in doc - token.type_ = tokenError; - token.start_ = beginDoc; - token.end_ = endDoc; - addError( - "A valid JSON document must be either an array or an object value.", - token); - return false; - } - } - return successful; -} - -bool Reader::readValue() { - Token token; - skipCommentTokens(token); - bool successful = true; - - if (collectComments_ && !commentsBefore_.empty()) { - // Remove newline characters at the end of the comments - size_t lastNonNewline = commentsBefore_.find_last_not_of("\r\n"); - if (lastNonNewline != std::string::npos) { - commentsBefore_.erase(lastNonNewline + 1); - } else { - commentsBefore_.clear(); - } - - currentValue().setComment(commentsBefore_, commentBefore); - commentsBefore_ = ""; - } - - switch (token.type_) { - case tokenObjectBegin: - successful = readObject(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenArrayBegin: - successful = readArray(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenNumber: - successful = decodeNumber(token); - break; - case tokenString: - successful = decodeString(token); - break; - case tokenTrue: - currentValue() = true; - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - break; - case tokenFalse: - currentValue() = false; - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - break; - case tokenNull: - currentValue() = Value(); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - break; - case tokenArraySeparator: - if (features_.allowDroppedNullPlaceholders_) { - // "Un-read" the current token and mark the current value as a null - // token. - current_--; - currentValue() = Value(); - currentValue().setOffsetStart(current_ - begin_ - 1); - currentValue().setOffsetLimit(current_ - begin_); - break; - } - // Else, fall through... - default: - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return addError("Syntax error: value, object or array expected.", token); - } - - if (collectComments_) { - lastValueEnd_ = current_; - lastValue_ = ¤tValue(); - } - - return successful; -} - -void Reader::skipCommentTokens(Token& token) { - if (features_.allowComments_) { - do { - readToken(token); - } while (token.type_ == tokenComment); - } else { - readToken(token); - } -} - -bool Reader::expectToken(TokenType type, Token& token, const char* message) { - readToken(token); - if (token.type_ != type) - return addError(message, token); - return true; -} - -bool Reader::readToken(Token& token) { - skipSpaces(); - token.start_ = current_; - Char c = getNextChar(); - bool ok = true; - switch (c) { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = readString(); - break; - case '/': - token.type_ = tokenComment; - ok = readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - token.type_ = tokenNumber; - readNumber(); - break; - case 't': - token.type_ = tokenTrue; - ok = match("rue", 3); - break; - case 'f': - token.type_ = tokenFalse; - ok = match("alse", 4); - break; - case 'n': - token.type_ = tokenNull; - ok = match("ull", 3); - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: - ok = false; - break; - } - if (!ok) - token.type_ = tokenError; - token.end_ = current_; - return true; -} - -void Reader::skipSpaces() { - while (current_ != end_) { - Char c = *current_; - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - ++current_; - else - break; - } -} - -bool Reader::match(Location pattern, int patternLength) { - if (end_ - current_ < patternLength) - return false; - int index = patternLength; - while (index--) - if (current_[index] != pattern[index]) - return false; - current_ += patternLength; - return true; -} - -bool Reader::readComment() { - Location commentBegin = current_ - 1; - Char c = getNextChar(); - bool successful = false; - if (c == '*') - successful = readCStyleComment(); - else if (c == '/') - successful = readCppStyleComment(); - if (!successful) - return false; - - if (collectComments_) { - CommentPlacement placement = commentBefore; - if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { - if (c != '*' || !containsNewLine(commentBegin, current_)) - placement = commentAfterOnSameLine; - } - - addComment(commentBegin, current_, placement); - } - return true; -} - -void -Reader::addComment(Location begin, Location end, CommentPlacement placement) { - assert(collectComments_); - if (placement == commentAfterOnSameLine) { - assert(lastValue_ != 0); - lastValue_->setComment(std::string(begin, end), placement); - } else { - commentsBefore_ += std::string(begin, end); - } -} - -bool Reader::readCStyleComment() { - while (current_ != end_) { - Char c = getNextChar(); - if (c == '*' && *current_ == '/') - break; - } - return getNextChar() == '/'; -} - -bool Reader::readCppStyleComment() { - while (current_ != end_) { - Char c = getNextChar(); - if (c == '\r' || c == '\n') - break; - } - return true; -} - -void Reader::readNumber() { - while (current_ != end_) { - if (!(*current_ >= '0' && *current_ <= '9') && - !in(*current_, '.', 'e', 'E', '+', '-')) - break; - ++current_; - } -} - -bool Reader::readString() { - Char c = 0; - while (current_ != end_) { - c = getNextChar(); - if (c == '\\') - getNextChar(); - else if (c == '"') - break; - } - return c == '"'; -} - -bool Reader::readObject(Token& tokenStart) { - Token tokenName; - std::string name; - currentValue() = Value(objectValue); - currentValue().setOffsetStart(tokenStart.start_ - begin_); - while (readToken(tokenName)) { - bool initialTokenOk = true; - while (tokenName.type_ == tokenComment && initialTokenOk) - initialTokenOk = readToken(tokenName); - if (!initialTokenOk) - break; - if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object - return true; - name = ""; - if (tokenName.type_ == tokenString) { - if (!decodeString(tokenName, name)) - return recoverFromError(tokenObjectEnd); - } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { - Value numberName; - if (!decodeNumber(tokenName, numberName)) - return recoverFromError(tokenObjectEnd); - name = numberName.asString(); - } else { - break; - } - - Token colon; - if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover( - "Missing ':' after object member name", colon, tokenObjectEnd); - } - Value& value = currentValue()[name]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenObjectEnd); - - Token comma; - if (!readToken(comma) || - (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && - comma.type_ != tokenComment)) { - return addErrorAndRecover( - "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); - } - bool finalizeTokenOk = true; - while (comma.type_ == tokenComment && finalizeTokenOk) - finalizeTokenOk = readToken(comma); - if (comma.type_ == tokenObjectEnd) - return true; - } - return addErrorAndRecover( - "Missing '}' or object member name", tokenName, tokenObjectEnd); -} - -bool Reader::readArray(Token& tokenStart) { - currentValue() = Value(arrayValue); - currentValue().setOffsetStart(tokenStart.start_ - begin_); - skipSpaces(); - if (*current_ == ']') // empty array - { - Token endArray; - readToken(endArray); - return true; - } - int index = 0; - for (;;) { - Value& value = currentValue()[index++]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenArrayEnd); - - Token token; - // Accept Comment after last item in the array. - ok = readToken(token); - while (token.type_ == tokenComment && ok) { - ok = readToken(token); - } - bool badTokenType = - (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); - if (!ok || badTokenType) { - return addErrorAndRecover( - "Missing ',' or ']' in array declaration", token, tokenArrayEnd); - } - if (token.type_ == tokenArrayEnd) - break; - } - return true; -} - -bool Reader::decodeNumber(Token& token) { - Value decoded; - if (!decodeNumber(token, decoded)) - return false; - currentValue() = decoded; - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeNumber(Token& token, Value& decoded) { - bool isDouble = false; - for (Location inspect = token.start_; inspect != token.end_; ++inspect) { - isDouble = isDouble || in(*inspect, '.', 'e', 'E', '+') || - (*inspect == '-' && inspect != token.start_); - } - if (isDouble) - return decodeDouble(token, decoded); - // Attempts to parse the number as an integer. If the number is - // larger than the maximum supported value of an integer then - // we decode the number as a double. - Location current = token.start_; - bool isNegative = *current == '-'; - if (isNegative) - ++current; - Value::LargestUInt maxIntegerValue = - isNegative ? Value::LargestUInt(-Value::minLargestInt) - : Value::maxLargestUInt; - Value::LargestUInt threshold = maxIntegerValue / 10; - Value::LargestUInt value = 0; - while (current < token.end_) { - Char c = *current++; - if (c < '0' || c > '9') - return addError("'" + std::string(token.start_, token.end_) + - "' is not a number.", - token); - Value::UInt digit(c - '0'); - if (value >= threshold) { - // We've hit or exceeded the max value divided by 10 (rounded down). If - // a) we've only just touched the limit, b) this is the last digit, and - // c) it's small enough to fit in that rounding delta, we're okay. - // Otherwise treat this number as a double to avoid overflow. - if (value > threshold || current != token.end_ || - digit > maxIntegerValue % 10) { - return decodeDouble(token, decoded); - } - } - value = value * 10 + digit; - } - if (isNegative) - decoded = -Value::LargestInt(value); - else if (value <= Value::LargestUInt(Value::maxInt)) - decoded = Value::LargestInt(value); - else - decoded = value; - return true; -} - -bool Reader::decodeDouble(Token& token) { - Value decoded; - if (!decodeDouble(token, decoded)) - return false; - currentValue() = decoded; - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeDouble(Token& token, Value& decoded) { - double value = 0; - const int bufferSize = 32; - int count; - int length = int(token.end_ - token.start_); - - // Sanity check to avoid buffer overflow exploits. - if (length < 0) { - return addError("Unable to parse token length", token); - } - - // Avoid using a string constant for the format control string given to - // sscanf, as this can cause hard to debug crashes on OS X. See here for more - // info: - // - // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html - char format[] = "%lf"; - - if (length <= bufferSize) { - Char buffer[bufferSize + 1]; - memcpy(buffer, token.start_, length); - buffer[length] = 0; - count = sscanf(buffer, format, &value); - } else { - std::string buffer(token.start_, token.end_); - count = sscanf(buffer.c_str(), format, &value); - } - - if (count != 1) - return addError("'" + std::string(token.start_, token.end_) + - "' is not a number.", - token); - decoded = value; - return true; -} - -bool Reader::decodeString(Token& token) { - std::string decoded; - if (!decodeString(token, decoded)) - return false; - currentValue() = decoded; - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeString(Token& token, std::string& decoded) { - decoded.reserve(token.end_ - token.start_ - 2); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' - while (current != end) { - Char c = *current++; - if (c == '"') - break; - else if (c == '\\') { - if (current == end) - return addError("Empty escape sequence in string", token, current); - Char escape = *current++; - switch (escape) { - case '"': - decoded += '"'; - break; - case '/': - decoded += '/'; - break; - case '\\': - decoded += '\\'; - break; - case 'b': - decoded += '\b'; - break; - case 'f': - decoded += '\f'; - break; - case 'n': - decoded += '\n'; - break; - case 'r': - decoded += '\r'; - break; - case 't': - decoded += '\t'; - break; - case 'u': { - unsigned int unicode; - if (!decodeUnicodeCodePoint(token, current, end, unicode)) - return false; - decoded += codePointToUTF8(unicode); - } break; - default: - return addError("Bad escape sequence in string", token, current); - } - } else { - decoded += c; - } - } - return true; -} - -bool Reader::decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode) { - - if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) - return false; - if (unicode >= 0xD800 && unicode <= 0xDBFF) { - // surrogate pairs - if (end - current < 6) - return addError( - "additional six characters expected to parse unicode surrogate pair.", - token, - current); - unsigned int surrogatePair; - if (*(current++) == '\\' && *(current++) == 'u') { - if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { - unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); - } else - return false; - } else - return addError("expecting another \\u token to begin the second half of " - "a unicode surrogate pair", - token, - current); - } - return true; -} - -bool Reader::decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& unicode) { - if (end - current < 4) - return addError( - "Bad unicode escape sequence in string: four digits expected.", - token, - current); - unicode = 0; - for (int index = 0; index < 4; ++index) { - Char c = *current++; - unicode *= 16; - if (c >= '0' && c <= '9') - unicode += c - '0'; - else if (c >= 'a' && c <= 'f') - unicode += c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - unicode += c - 'A' + 10; - else - return addError( - "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, - current); - } - return true; -} - -bool -Reader::addError(const std::string& message, Token& token, Location extra) { - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = extra; - errors_.push_back(info); - return false; -} - -bool Reader::recoverFromError(TokenType skipUntilToken) { - int errorCount = int(errors_.size()); - Token skip; - for (;;) { - if (!readToken(skip)) - errors_.resize(errorCount); // discard errors caused by recovery - if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) - break; - } - errors_.resize(errorCount); - return false; -} - -bool Reader::addErrorAndRecover(const std::string& message, - Token& token, - TokenType skipUntilToken) { - addError(message, token); - return recoverFromError(skipUntilToken); -} - -Value& Reader::currentValue() { return *(nodes_.top()); } - -Reader::Char Reader::getNextChar() { - if (current_ == end_) - return 0; - return *current_++; -} - -void Reader::getLocationLineAndColumn(Location location, - int& line, - int& column) const { - Location current = begin_; - Location lastLineStart = current; - line = 0; - while (current < location && current != end_) { - Char c = *current++; - if (c == '\r') { - if (*current == '\n') - ++current; - lastLineStart = current; - ++line; - } else if (c == '\n') { - lastLineStart = current; - ++line; - } - } - // column & line start at 1 - column = int(location - lastLineStart) + 1; - ++line; -} - -std::string Reader::getLocationLineAndColumn(Location location) const { - int line, column; - getLocationLineAndColumn(location, line, column); - char buffer[18 + 16 + 16 + 1]; -#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) -#if defined(WINCE) - _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); -#else - sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column); -#endif -#else - snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); -#endif - return buffer; -} - -// Deprecated. Preserved for backward compatibility -std::string Reader::getFormatedErrorMessages() const { - return getFormattedErrorMessages(); -} - -std::string Reader::getFormattedErrorMessages() const { - std::string formattedMessage; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; - formattedMessage += - "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; - formattedMessage += " " + error.message_ + "\n"; - if (error.extra_) - formattedMessage += - "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; - } - return formattedMessage; -} - -std::vector Reader::getStructuredErrors() const { - std::vector allErrors; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; - Reader::StructuredError structured; - structured.offset_start = error.token_.start_ - begin_; - structured.offset_limit = error.token_.end_ - begin_; - structured.message = error.message_; - allErrors.push_back(structured); - } - return allErrors; -} - -std::istream& operator>>(std::istream& sin, Value& root) { - Json::Reader reader; - bool ok = reader.parse(sin, root, true); - if (!ok) { - fprintf(stderr, - "Error from reader: %s", - reader.getFormattedErrorMessages().c_str()); - - JSON_FAIL_MESSAGE("reader error"); - } - return sin; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_reader.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_batchallocator.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED -#define JSONCPP_BATCHALLOCATOR_H_INCLUDED - -#include -#include - -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - -namespace Json { - -/* Fast memory allocator. - * - * This memory allocator allocates memory for a batch of object (specified by - * the page size, the number of object in each page). - * - * It does not allow the destruction of a single object. All the allocated - * objects can be destroyed at once. The memory can be either released or reused - * for future allocation. - * - * The in-place new operator must be used to construct the object using the - * pointer returned by allocate. - */ -template -class BatchAllocator { -public: - BatchAllocator(unsigned int objectsPerPage = 255) - : freeHead_(0), objectsPerPage_(objectsPerPage) { - // printf( "Size: %d => %s\n", sizeof(AllocatedType), - // typeid(AllocatedType).name() ); - assert(sizeof(AllocatedType) * objectPerAllocation >= - sizeof(AllocatedType*)); // We must be able to store a slist in the - // object free space. - assert(objectsPerPage >= 16); - batches_ = allocateBatch(0); // allocated a dummy page - currentBatch_ = batches_; - } - - ~BatchAllocator() { - for (BatchInfo* batch = batches_; batch;) { - BatchInfo* nextBatch = batch->next_; - free(batch); - batch = nextBatch; - } - } - - /// allocate space for an array of objectPerAllocation object. - /// @warning it is the responsability of the caller to call objects - /// constructors. - AllocatedType* allocate() { - if (freeHead_) // returns node from free list. - { - AllocatedType* object = freeHead_; - freeHead_ = *(AllocatedType**)object; - return object; - } - if (currentBatch_->used_ == currentBatch_->end_) { - currentBatch_ = currentBatch_->next_; - while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_) - currentBatch_ = currentBatch_->next_; - - if (!currentBatch_) // no free batch found, allocate a new one - { - currentBatch_ = allocateBatch(objectsPerPage_); - currentBatch_->next_ = batches_; // insert at the head of the list - batches_ = currentBatch_; - } - } - AllocatedType* allocated = currentBatch_->used_; - currentBatch_->used_ += objectPerAllocation; - return allocated; - } - - /// Release the object. - /// @warning it is the responsability of the caller to actually destruct the - /// object. - void release(AllocatedType* object) { - assert(object != 0); - *(AllocatedType**)object = freeHead_; - freeHead_ = object; - } - -private: - struct BatchInfo { - BatchInfo* next_; - AllocatedType* used_; - AllocatedType* end_; - AllocatedType buffer_[objectPerAllocation]; - }; - - // disabled copy constructor and assignement operator. - BatchAllocator(const BatchAllocator&); - void operator=(const BatchAllocator&); - - static BatchInfo* allocateBatch(unsigned int objectsPerPage) { - const unsigned int mallocSize = - sizeof(BatchInfo) - sizeof(AllocatedType) * objectPerAllocation + - sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; - BatchInfo* batch = static_cast(malloc(mallocSize)); - batch->next_ = 0; - batch->used_ = batch->buffer_; - batch->end_ = batch->buffer_ + objectsPerPage; - return batch; - } - - BatchInfo* batches_; - BatchInfo* currentBatch_; - /// Head of a single linked list within the allocated space of freeed object - AllocatedType* freeHead_; - unsigned int objectsPerPage_; -}; - -} // namespace Json - -#endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION - -#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_batchallocator.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_valueiterator.inl -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -// included by json_value.cpp - -namespace Json { - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIteratorBase -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIteratorBase::ValueIteratorBase() -#ifndef JSON_VALUE_USE_INTERNAL_MAP - : current_(), isNull_(true) { -} -#else - : isArray_(true), isNull_(true) { - iterator_.array_ = ValueInternalArray::IteratorState(); -} -#endif - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueIteratorBase::ValueIteratorBase( - const Value::ObjectValues::iterator& current) - : current_(current), isNull_(false) {} -#else -ValueIteratorBase::ValueIteratorBase( - const ValueInternalArray::IteratorState& state) - : isArray_(true) { - iterator_.array_ = state; -} - -ValueIteratorBase::ValueIteratorBase( - const ValueInternalMap::IteratorState& state) - : isArray_(false) { - iterator_.map_ = state; -} -#endif - -Value& ValueIteratorBase::deref() const { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - return current_->second; -#else - if (isArray_) - return ValueInternalArray::dereference(iterator_.array_); - return ValueInternalMap::value(iterator_.map_); -#endif -} - -void ValueIteratorBase::increment() { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ++current_; -#else - if (isArray_) - ValueInternalArray::increment(iterator_.array_); - ValueInternalMap::increment(iterator_.map_); -#endif -} - -void ValueIteratorBase::decrement() { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - --current_; -#else - if (isArray_) - ValueInternalArray::decrement(iterator_.array_); - ValueInternalMap::decrement(iterator_.map_); -#endif -} - -ValueIteratorBase::difference_type -ValueIteratorBase::computeDistance(const SelfType& other) const { -#ifndef JSON_VALUE_USE_INTERNAL_MAP -#ifdef JSON_USE_CPPTL_SMALLMAP - return current_ - other.current_; -#else - // Iterator for null value are initialized using the default - // constructor, which initialize current_ to the default - // std::map::iterator. As begin() and end() are two instance - // of the default std::map::iterator, they can not be compared. - // To allow this, we handle this comparison specifically. - if (isNull_ && other.isNull_) { - return 0; - } - - // Usage of std::distance is not portable (does not compile with Sun Studio 12 - // RogueWave STL, - // which is the one used by default). - // Using a portable hand-made version for non random iterator instead: - // return difference_type( std::distance( current_, other.current_ ) ); - difference_type myDistance = 0; - for (Value::ObjectValues::iterator it = current_; it != other.current_; - ++it) { - ++myDistance; - } - return myDistance; -#endif -#else - if (isArray_) - return ValueInternalArray::distance(iterator_.array_, - other.iterator_.array_); - return ValueInternalMap::distance(iterator_.map_, other.iterator_.map_); -#endif -} - -bool ValueIteratorBase::isEqual(const SelfType& other) const { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - if (isNull_) { - return other.isNull_; - } - return current_ == other.current_; -#else - if (isArray_) - return ValueInternalArray::equals(iterator_.array_, other.iterator_.array_); - return ValueInternalMap::equals(iterator_.map_, other.iterator_.map_); -#endif -} - -void ValueIteratorBase::copy(const SelfType& other) { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - current_ = other.current_; - isNull_ = other.isNull_; -#else - if (isArray_) - iterator_.array_ = other.iterator_.array_; - iterator_.map_ = other.iterator_.map_; -#endif -} - -Value ValueIteratorBase::key() const { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const Value::CZString czstring = (*current_).first; - if (czstring.c_str()) { - if (czstring.isStaticString()) - return Value(StaticString(czstring.c_str())); - return Value(czstring.c_str()); - } - return Value(czstring.index()); -#else - if (isArray_) - return Value(ValueInternalArray::indexOf(iterator_.array_)); - bool isStatic; - const char* memberName = ValueInternalMap::key(iterator_.map_, isStatic); - if (isStatic) - return Value(StaticString(memberName)); - return Value(memberName); -#endif -} - -UInt ValueIteratorBase::index() const { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const Value::CZString czstring = (*current_).first; - if (!czstring.c_str()) - return czstring.index(); - return Value::UInt(-1); -#else - if (isArray_) - return Value::UInt(ValueInternalArray::indexOf(iterator_.array_)); - return Value::UInt(-1); -#endif -} - -const char* ValueIteratorBase::memberName() const { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const char* name = (*current_).first.c_str(); - return name ? name : ""; -#else - if (!isArray_) - return ValueInternalMap::key(iterator_.map_); - return ""; -#endif -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueConstIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueConstIterator::ValueConstIterator() {} - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueConstIterator::ValueConstIterator( - const Value::ObjectValues::iterator& current) - : ValueIteratorBase(current) {} -#else -ValueConstIterator::ValueConstIterator( - const ValueInternalArray::IteratorState& state) - : ValueIteratorBase(state) {} - -ValueConstIterator::ValueConstIterator( - const ValueInternalMap::IteratorState& state) - : ValueIteratorBase(state) {} -#endif - -ValueConstIterator& ValueConstIterator:: -operator=(const ValueIteratorBase& other) { - copy(other); - return *this; -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIterator::ValueIterator() {} - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) - : ValueIteratorBase(current) {} -#else -ValueIterator::ValueIterator(const ValueInternalArray::IteratorState& state) - : ValueIteratorBase(state) {} - -ValueIterator::ValueIterator(const ValueInternalMap::IteratorState& state) - : ValueIteratorBase(state) {} -#endif - -ValueIterator::ValueIterator(const ValueConstIterator& other) - : ValueIteratorBase(other) {} - -ValueIterator::ValueIterator(const ValueIterator& other) - : ValueIteratorBase(other) {} - -ValueIterator& ValueIterator::operator=(const SelfType& other) { - copy(other); - return *this; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_valueiterator.inl -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_value.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2011 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR -#include "json_batchallocator.h" -#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#ifdef JSON_USE_CPPTL -#include -#endif -#include // size_t - -#define JSON_ASSERT_UNREACHABLE assert(false) - -namespace Json { - -// This is a walkaround to avoid the static initialization of Value::null. -// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of -// 8 (instead of 4) as a bit of future-proofing. -#if defined(__ARMEL__) -#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) -#else -#define ALIGNAS(byte_alignment) -#endif -static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; -const unsigned char& kNullRef = kNull[0]; -const Value& Value::null = reinterpret_cast(kNullRef); - -const Int Value::minInt = Int(~(UInt(-1) / 2)); -const Int Value::maxInt = Int(UInt(-1) / 2); -const UInt Value::maxUInt = UInt(-1); -#if defined(JSON_HAS_INT64) -const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); -const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); -const UInt64 Value::maxUInt64 = UInt64(-1); -// The constant is hard-coded because some compiler have trouble -// converting Value::maxUInt64 to a double correctly (AIX/xlC). -// Assumes that UInt64 is a 64 bits integer. -static const double maxUInt64AsDouble = 18446744073709551615.0; -#endif // defined(JSON_HAS_INT64) -const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); -const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); -const LargestUInt Value::maxLargestUInt = LargestUInt(-1); - -/// Unknown size marker -static const unsigned int unknown = (unsigned)-1; - -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) -template -static inline bool InRange(double d, T min, U max) { - return d >= min && d <= max; -} -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) -static inline double integerToDouble(Json::UInt64 value) { - return static_cast(Int64(value / 2)) * 2.0 + Int64(value & 1); -} - -template static inline double integerToDouble(T value) { - return static_cast(value); -} - -template -static inline bool InRange(double d, T min, U max) { - return d >= integerToDouble(min) && d <= integerToDouble(max); -} -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - -/** Duplicates the specified string value. - * @param value Pointer to the string to duplicate. Must be zero-terminated if - * length is "unknown". - * @param length Length of the value. if equals to unknown, then it will be - * computed using strlen(value). - * @return Pointer on the duplicate instance of string. - */ -static inline char* duplicateStringValue(const char* value, - unsigned int length = unknown) { - if (length == unknown) - length = (unsigned int)strlen(value); - - // Avoid an integer overflow in the call to malloc below by limiting length - // to a sane value. - if (length >= (unsigned)Value::maxInt) - length = Value::maxInt - 1; - - char* newString = static_cast(malloc(length + 1)); - JSON_ASSERT_MESSAGE(newString != 0, - "in Json::Value::duplicateStringValue(): " - "Failed to allocate string value buffer"); - memcpy(newString, value, length); - newString[length] = 0; - return newString; -} - -/** Free the string duplicated by duplicateStringValue(). - */ -static inline void releaseStringValue(char* value) { free(value); } - -} // namespace Json - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ValueInternals... -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -#if !defined(JSON_IS_AMALGAMATION) -#ifdef JSON_VALUE_USE_INTERNAL_MAP -#include "json_internalarray.inl" -#include "json_internalmap.inl" -#endif // JSON_VALUE_USE_INTERNAL_MAP - -#include "json_valueiterator.inl" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CommentInfo -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -Value::CommentInfo::CommentInfo() : comment_(0) {} - -Value::CommentInfo::~CommentInfo() { - if (comment_) - releaseStringValue(comment_); -} - -void Value::CommentInfo::setComment(const char* text) { - if (comment_) - releaseStringValue(comment_); - JSON_ASSERT(text != 0); - JSON_ASSERT_MESSAGE( - text[0] == '\0' || text[0] == '/', - "in Json::Value::setComment(): Comments must start with /"); - // It seems that /**/ style comments are acceptable as well. - comment_ = duplicateStringValue(text); -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CZString -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -#ifndef JSON_VALUE_USE_INTERNAL_MAP - -// Notes: index_ indicates if the string was allocated when -// a string is stored. - -Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {} - -Value::CZString::CZString(const char* cstr, DuplicationPolicy allocate) - : cstr_(allocate == duplicate ? duplicateStringValue(cstr) : cstr), - index_(allocate) {} - -Value::CZString::CZString(const CZString& other) - : cstr_(other.index_ != noDuplication && other.cstr_ != 0 - ? duplicateStringValue(other.cstr_) - : other.cstr_), - index_(other.cstr_ - ? (other.index_ == noDuplication ? noDuplication : duplicate) - : other.index_) {} - -Value::CZString::~CZString() { - if (cstr_ && index_ == duplicate) - releaseStringValue(const_cast(cstr_)); -} - -void Value::CZString::swap(CZString& other) { - std::swap(cstr_, other.cstr_); - std::swap(index_, other.index_); -} - -Value::CZString& Value::CZString::operator=(CZString other) { - swap(other); - return *this; -} - -bool Value::CZString::operator<(const CZString& other) const { - if (cstr_) - return strcmp(cstr_, other.cstr_) < 0; - return index_ < other.index_; -} - -bool Value::CZString::operator==(const CZString& other) const { - if (cstr_) - return strcmp(cstr_, other.cstr_) == 0; - return index_ == other.index_; -} - -ArrayIndex Value::CZString::index() const { return index_; } - -const char* Value::CZString::c_str() const { return cstr_; } - -bool Value::CZString::isStaticString() const { return index_ == noDuplication; } - -#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::Value -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -/*! \internal Default constructor initialization must be equivalent to: - * memset( this, 0, sizeof(Value) ) - * This optimization is used in ValueInternalMap fast allocator. - */ -Value::Value(ValueType type) - : type_(type), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - switch (type) { - case nullValue: - break; - case intValue: - case uintValue: - value_.int_ = 0; - break; - case realValue: - value_.real_ = 0.0; - break; - case stringValue: - value_.string_ = 0; - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(); - break; -#else - case arrayValue: - value_.array_ = arrayAllocator()->newArray(); - break; - case objectValue: - value_.map_ = mapAllocator()->newMap(); - break; -#endif - case booleanValue: - value_.bool_ = false; - break; - default: - JSON_ASSERT_UNREACHABLE; - } -} - -Value::Value(UInt value) - : type_(uintValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.uint_ = value; -} - -Value::Value(Int value) - : type_(intValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.int_ = value; -} - -#if defined(JSON_HAS_INT64) -Value::Value(Int64 value) - : type_(intValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.int_ = value; -} - -Value::Value(UInt64 value) - : type_(uintValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.uint_ = value; -} -#endif // defined(JSON_HAS_INT64) - -Value::Value(double value) - : type_(realValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.real_ = value; -} - -Value::Value(const char* value) - : type_(stringValue), allocated_(true) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.string_ = duplicateStringValue(value); -} - -Value::Value(const char* beginValue, const char* endValue) - : type_(stringValue), allocated_(true) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.string_ = - duplicateStringValue(beginValue, (unsigned int)(endValue - beginValue)); -} - -Value::Value(const std::string& value) - : type_(stringValue), allocated_(true) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.string_ = - duplicateStringValue(value.c_str(), (unsigned int)value.length()); -} - -Value::Value(const StaticString& value) - : type_(stringValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.string_ = const_cast(value.c_str()); -} - -#ifdef JSON_USE_CPPTL -Value::Value(const CppTL::ConstString& value) - : type_(stringValue), allocated_(true) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.string_ = duplicateStringValue(value, value.length()); -} -#endif - -Value::Value(bool value) - : type_(booleanValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.bool_ = value; -} - -Value::Value(const Value& other) - : type_(other.type_), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(other.start_), limit_(other.limit_) { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - value_ = other.value_; - break; - case stringValue: - if (other.value_.string_) { - value_.string_ = duplicateStringValue(other.value_.string_); - allocated_ = true; - } else { - value_.string_ = 0; - allocated_ = false; - } - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(*other.value_.map_); - break; -#else - case arrayValue: - value_.array_ = arrayAllocator()->newArrayCopy(*other.value_.array_); - break; - case objectValue: - value_.map_ = mapAllocator()->newMapCopy(*other.value_.map_); - break; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - if (other.comments_) { - comments_ = new CommentInfo[numberOfCommentPlacement]; - for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { - const CommentInfo& otherComment = other.comments_[comment]; - if (otherComment.comment_) - comments_[comment].setComment(otherComment.comment_); - } - } -} - -Value::~Value() { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if (allocated_) - releaseStringValue(value_.string_); - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - delete value_.map_; - break; -#else - case arrayValue: - arrayAllocator()->destructArray(value_.array_); - break; - case objectValue: - mapAllocator()->destructMap(value_.map_); - break; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - - if (comments_) - delete[] comments_; -} - -Value& Value::operator=(Value other) { - swap(other); - return *this; -} - -void Value::swap(Value& other) { - ValueType temp = type_; - type_ = other.type_; - other.type_ = temp; - std::swap(value_, other.value_); - int temp2 = allocated_; - allocated_ = other.allocated_; - other.allocated_ = temp2; - std::swap(start_, other.start_); - std::swap(limit_, other.limit_); -} - -ValueType Value::type() const { return type_; } - -int Value::compare(const Value& other) const { - if (*this < other) - return -1; - if (*this > other) - return 1; - return 0; -} - -bool Value::operator<(const Value& other) const { - int typeDelta = type_ - other.type_; - if (typeDelta) - return typeDelta < 0 ? true : false; - switch (type_) { - case nullValue: - return false; - case intValue: - return value_.int_ < other.value_.int_; - case uintValue: - return value_.uint_ < other.value_.uint_; - case realValue: - return value_.real_ < other.value_.real_; - case booleanValue: - return value_.bool_ < other.value_.bool_; - case stringValue: - return (value_.string_ == 0 && other.value_.string_) || - (other.value_.string_ && value_.string_ && - strcmp(value_.string_, other.value_.string_) < 0); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: { - int delta = int(value_.map_->size() - other.value_.map_->size()); - if (delta) - return delta < 0; - return (*value_.map_) < (*other.value_.map_); - } -#else - case arrayValue: - return value_.array_->compare(*(other.value_.array_)) < 0; - case objectValue: - return value_.map_->compare(*(other.value_.map_)) < 0; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool Value::operator<=(const Value& other) const { return !(other < *this); } - -bool Value::operator>=(const Value& other) const { return !(*this < other); } - -bool Value::operator>(const Value& other) const { return other < *this; } - -bool Value::operator==(const Value& other) const { - // if ( type_ != other.type_ ) - // GCC 2.95.3 says: - // attempt to take address of bit-field structure member `Json::Value::type_' - // Beats me, but a temp solves the problem. - int temp = other.type_; - if (type_ != temp) - return false; - switch (type_) { - case nullValue: - return true; - case intValue: - return value_.int_ == other.value_.int_; - case uintValue: - return value_.uint_ == other.value_.uint_; - case realValue: - return value_.real_ == other.value_.real_; - case booleanValue: - return value_.bool_ == other.value_.bool_; - case stringValue: - return (value_.string_ == other.value_.string_) || - (other.value_.string_ && value_.string_ && - strcmp(value_.string_, other.value_.string_) == 0); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - return value_.map_->size() == other.value_.map_->size() && - (*value_.map_) == (*other.value_.map_); -#else - case arrayValue: - return value_.array_->compare(*(other.value_.array_)) == 0; - case objectValue: - return value_.map_->compare(*(other.value_.map_)) == 0; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool Value::operator!=(const Value& other) const { return !(*this == other); } - -const char* Value::asCString() const { - JSON_ASSERT_MESSAGE(type_ == stringValue, - "in Json::Value::asCString(): requires stringValue"); - return value_.string_; -} - -std::string Value::asString() const { - switch (type_) { - case nullValue: - return ""; - case stringValue: - return value_.string_ ? value_.string_ : ""; - case booleanValue: - return value_.bool_ ? "true" : "false"; - case intValue: - return valueToString(value_.int_); - case uintValue: - return valueToString(value_.uint_); - case realValue: - return valueToString(value_.real_); - default: - JSON_FAIL_MESSAGE("Type is not convertible to string"); - } -} - -#ifdef JSON_USE_CPPTL -CppTL::ConstString Value::asConstString() const { - return CppTL::ConstString(asString().c_str()); -} -#endif - -Value::Int Value::asInt() const { - switch (type_) { - case intValue: - JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); - return Int(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); - return Int(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), - "double out of Int range"); - return Int(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to Int."); -} - -Value::UInt Value::asUInt() const { - switch (type_) { - case intValue: - JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); - return UInt(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); - return UInt(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), - "double out of UInt range"); - return UInt(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to UInt."); -} - -#if defined(JSON_HAS_INT64) - -Value::Int64 Value::asInt64() const { - switch (type_) { - case intValue: - return Int64(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); - return Int64(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), - "double out of Int64 range"); - return Int64(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to Int64."); -} - -Value::UInt64 Value::asUInt64() const { - switch (type_) { - case intValue: - JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); - return UInt64(value_.int_); - case uintValue: - return UInt64(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), - "double out of UInt64 range"); - return UInt64(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); -} -#endif // if defined(JSON_HAS_INT64) - -LargestInt Value::asLargestInt() const { -#if defined(JSON_NO_INT64) - return asInt(); -#else - return asInt64(); -#endif -} - -LargestUInt Value::asLargestUInt() const { -#if defined(JSON_NO_INT64) - return asUInt(); -#else - return asUInt64(); -#endif -} - -double Value::asDouble() const { - switch (type_) { - case intValue: - return static_cast(value_.int_); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast(value_.uint_); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return integerToDouble(value_.uint_); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return value_.real_; - case nullValue: - return 0.0; - case booleanValue: - return value_.bool_ ? 1.0 : 0.0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to double."); -} - -float Value::asFloat() const { - switch (type_) { - case intValue: - return static_cast(value_.int_); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast(value_.uint_); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return integerToDouble(value_.uint_); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return static_cast(value_.real_); - case nullValue: - return 0.0; - case booleanValue: - return value_.bool_ ? 1.0f : 0.0f; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to float."); -} - -bool Value::asBool() const { - switch (type_) { - case booleanValue: - return value_.bool_; - case nullValue: - return false; - case intValue: - return value_.int_ ? true : false; - case uintValue: - return value_.uint_ ? true : false; - case realValue: - return value_.real_ ? true : false; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to bool."); -} - -bool Value::isConvertibleTo(ValueType other) const { - switch (other) { - case nullValue: - return (isNumeric() && asDouble() == 0.0) || - (type_ == booleanValue && value_.bool_ == false) || - (type_ == stringValue && asString() == "") || - (type_ == arrayValue && value_.map_->size() == 0) || - (type_ == objectValue && value_.map_->size() == 0) || - type_ == nullValue; - case intValue: - return isInt() || - (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || - type_ == booleanValue || type_ == nullValue; - case uintValue: - return isUInt() || - (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || - type_ == booleanValue || type_ == nullValue; - case realValue: - return isNumeric() || type_ == booleanValue || type_ == nullValue; - case booleanValue: - return isNumeric() || type_ == booleanValue || type_ == nullValue; - case stringValue: - return isNumeric() || type_ == booleanValue || type_ == stringValue || - type_ == nullValue; - case arrayValue: - return type_ == arrayValue || type_ == nullValue; - case objectValue: - return type_ == objectValue || type_ == nullValue; - } - JSON_ASSERT_UNREACHABLE; - return false; -} - -/// Number of values in array or object -ArrayIndex Value::size() const { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - case stringValue: - return 0; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: // size of the array is highest index + 1 - if (!value_.map_->empty()) { - ObjectValues::const_iterator itLast = value_.map_->end(); - --itLast; - return (*itLast).first.index() + 1; - } - return 0; - case objectValue: - return ArrayIndex(value_.map_->size()); -#else - case arrayValue: - return Int(value_.array_->size()); - case objectValue: - return Int(value_.map_->size()); -#endif - } - JSON_ASSERT_UNREACHABLE; - return 0; // unreachable; -} - -bool Value::empty() const { - if (isNull() || isArray() || isObject()) - return size() == 0u; - else - return false; -} - -bool Value::operator!() const { return isNull(); } - -void Value::clear() { - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || - type_ == objectValue, - "in Json::Value::clear(): requires complex value"); - start_ = 0; - limit_ = 0; - switch (type_) { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_->clear(); - break; -#else - case arrayValue: - value_.array_->clear(); - break; - case objectValue: - value_.map_->clear(); - break; -#endif - default: - break; - } -} - -void Value::resize(ArrayIndex newSize) { - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, - "in Json::Value::resize(): requires arrayValue"); - if (type_ == nullValue) - *this = Value(arrayValue); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ArrayIndex oldSize = size(); - if (newSize == 0) - clear(); - else if (newSize > oldSize) - (*this)[newSize - 1]; - else { - for (ArrayIndex index = newSize; index < oldSize; ++index) { - value_.map_->erase(index); - } - assert(size() == newSize); - } -#else - value_.array_->resize(newSize); -#endif -} - -Value& Value::operator[](ArrayIndex index) { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == arrayValue, - "in Json::Value::operator[](ArrayIndex): requires arrayValue"); - if (type_ == nullValue) - *this = Value(arrayValue); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString key(index); - ObjectValues::iterator it = value_.map_->lower_bound(key); - if (it != value_.map_->end() && (*it).first == key) - return (*it).second; - - ObjectValues::value_type defaultValue(key, null); - it = value_.map_->insert(it, defaultValue); - return (*it).second; -#else - return value_.array_->resolveReference(index); -#endif -} - -Value& Value::operator[](int index) { - JSON_ASSERT_MESSAGE( - index >= 0, - "in Json::Value::operator[](int index): index cannot be negative"); - return (*this)[ArrayIndex(index)]; -} - -const Value& Value::operator[](ArrayIndex index) const { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == arrayValue, - "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); - if (type_ == nullValue) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString key(index); - ObjectValues::const_iterator it = value_.map_->find(key); - if (it == value_.map_->end()) - return null; - return (*it).second; -#else - Value* value = value_.array_->find(index); - return value ? *value : null; -#endif -} - -const Value& Value::operator[](int index) const { - JSON_ASSERT_MESSAGE( - index >= 0, - "in Json::Value::operator[](int index) const: index cannot be negative"); - return (*this)[ArrayIndex(index)]; -} - -Value& Value::operator[](const char* key) { - return resolveReference(key, false); -} - -Value& Value::resolveReference(const char* key, bool isStatic) { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::resolveReference(): requires objectValue"); - if (type_ == nullValue) - *this = Value(objectValue); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey( - key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy); - ObjectValues::iterator it = value_.map_->lower_bound(actualKey); - if (it != value_.map_->end() && (*it).first == actualKey) - return (*it).second; - - ObjectValues::value_type defaultValue(actualKey, null); - it = value_.map_->insert(it, defaultValue); - Value& value = (*it).second; - return value; -#else - return value_.map_->resolveReference(key, isStatic); -#endif -} - -Value Value::get(ArrayIndex index, const Value& defaultValue) const { - const Value* value = &((*this)[index]); - return value == &null ? defaultValue : *value; -} - -bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } - -const Value& Value::operator[](const char* key) const { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::operator[](char const*)const: requires objectValue"); - if (type_ == nullValue) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey(key, CZString::noDuplication); - ObjectValues::const_iterator it = value_.map_->find(actualKey); - if (it == value_.map_->end()) - return null; - return (*it).second; -#else - const Value* value = value_.map_->find(key); - return value ? *value : null; -#endif -} - -Value& Value::operator[](const std::string& key) { - return (*this)[key.c_str()]; -} - -const Value& Value::operator[](const std::string& key) const { - return (*this)[key.c_str()]; -} - -Value& Value::operator[](const StaticString& key) { - return resolveReference(key, true); -} - -#ifdef JSON_USE_CPPTL -Value& Value::operator[](const CppTL::ConstString& key) { - return (*this)[key.c_str()]; -} - -const Value& Value::operator[](const CppTL::ConstString& key) const { - return (*this)[key.c_str()]; -} -#endif - -Value& Value::append(const Value& value) { return (*this)[size()] = value; } - -Value Value::get(const char* key, const Value& defaultValue) const { - const Value* value = &((*this)[key]); - return value == &null ? defaultValue : *value; -} - -Value Value::get(const std::string& key, const Value& defaultValue) const { - return get(key.c_str(), defaultValue); -} - -Value Value::removeMember(const char* key) { - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, - "in Json::Value::removeMember(): requires objectValue"); - if (type_ == nullValue) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey(key, CZString::noDuplication); - ObjectValues::iterator it = value_.map_->find(actualKey); - if (it == value_.map_->end()) - return null; - Value old(it->second); - value_.map_->erase(it); - return old; -#else - Value* value = value_.map_->find(key); - if (value) { - Value old(*value); - value_.map_.remove(key); - return old; - } else { - return null; - } -#endif -} - -Value Value::removeMember(const std::string& key) { - return removeMember(key.c_str()); -} - -#ifdef JSON_USE_CPPTL -Value Value::get(const CppTL::ConstString& key, - const Value& defaultValue) const { - return get(key.c_str(), defaultValue); -} -#endif - -bool Value::isMember(const char* key) const { - const Value* value = &((*this)[key]); - return value != &null; -} - -bool Value::isMember(const std::string& key) const { - return isMember(key.c_str()); -} - -#ifdef JSON_USE_CPPTL -bool Value::isMember(const CppTL::ConstString& key) const { - return isMember(key.c_str()); -} -#endif - -Value::Members Value::getMemberNames() const { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::getMemberNames(), value must be objectValue"); - if (type_ == nullValue) - return Value::Members(); - Members members; - members.reserve(value_.map_->size()); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ObjectValues::const_iterator it = value_.map_->begin(); - ObjectValues::const_iterator itEnd = value_.map_->end(); - for (; it != itEnd; ++it) - members.push_back(std::string((*it).first.c_str())); -#else - ValueInternalMap::IteratorState it; - ValueInternalMap::IteratorState itEnd; - value_.map_->makeBeginIterator(it); - value_.map_->makeEndIterator(itEnd); - for (; !ValueInternalMap::equals(it, itEnd); ValueInternalMap::increment(it)) - members.push_back(std::string(ValueInternalMap::key(it))); -#endif - return members; -} -// -//# ifdef JSON_USE_CPPTL -// EnumMemberNames -// Value::enumMemberNames() const -//{ -// if ( type_ == objectValue ) -// { -// return CppTL::Enum::any( CppTL::Enum::transform( -// CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), -// MemberNamesTransform() ) ); -// } -// return EnumMemberNames(); -//} -// -// -// EnumValues -// Value::enumValues() const -//{ -// if ( type_ == objectValue || type_ == arrayValue ) -// return CppTL::Enum::anyValues( *(value_.map_), -// CppTL::Type() ); -// return EnumValues(); -//} -// -//# endif - -static bool IsIntegral(double d) { - double integral_part; - return modf(d, &integral_part) == 0.0; -} - -bool Value::isNull() const { return type_ == nullValue; } - -bool Value::isBool() const { return type_ == booleanValue; } - -bool Value::isInt() const { - switch (type_) { - case intValue: - return value_.int_ >= minInt && value_.int_ <= maxInt; - case uintValue: - return value_.uint_ <= UInt(maxInt); - case realValue: - return value_.real_ >= minInt && value_.real_ <= maxInt && - IsIntegral(value_.real_); - default: - break; - } - return false; -} - -bool Value::isUInt() const { - switch (type_) { - case intValue: - return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); - case uintValue: - return value_.uint_ <= maxUInt; - case realValue: - return value_.real_ >= 0 && value_.real_ <= maxUInt && - IsIntegral(value_.real_); - default: - break; - } - return false; -} - -bool Value::isInt64() const { -#if defined(JSON_HAS_INT64) - switch (type_) { - case intValue: - return true; - case uintValue: - return value_.uint_ <= UInt64(maxInt64); - case realValue: - // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a - // double, so double(maxInt64) will be rounded up to 2^63. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= double(minInt64) && - value_.real_ < double(maxInt64) && IsIntegral(value_.real_); - default: - break; - } -#endif // JSON_HAS_INT64 - return false; -} - -bool Value::isUInt64() const { -#if defined(JSON_HAS_INT64) - switch (type_) { - case intValue: - return value_.int_ >= 0; - case uintValue: - return true; - case realValue: - // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a - // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && - IsIntegral(value_.real_); - default: - break; - } -#endif // JSON_HAS_INT64 - return false; -} - -bool Value::isIntegral() const { -#if defined(JSON_HAS_INT64) - return isInt64() || isUInt64(); -#else - return isInt() || isUInt(); -#endif -} - -bool Value::isDouble() const { return type_ == realValue || isIntegral(); } - -bool Value::isNumeric() const { return isIntegral() || isDouble(); } - -bool Value::isString() const { return type_ == stringValue; } - -bool Value::isArray() const { return type_ == arrayValue; } - -bool Value::isObject() const { return type_ == objectValue; } - -void Value::setComment(const char* comment, CommentPlacement placement) { - if (!comments_) - comments_ = new CommentInfo[numberOfCommentPlacement]; - comments_[placement].setComment(comment); -} - -void Value::setComment(const std::string& comment, CommentPlacement placement) { - setComment(comment.c_str(), placement); -} - -bool Value::hasComment(CommentPlacement placement) const { - return comments_ != 0 && comments_[placement].comment_ != 0; -} - -std::string Value::getComment(CommentPlacement placement) const { - if (hasComment(placement)) - return comments_[placement].comment_; - return ""; -} - -void Value::setOffsetStart(size_t start) { start_ = start; } - -void Value::setOffsetLimit(size_t limit) { limit_ = limit; } - -size_t Value::getOffsetStart() const { return start_; } - -size_t Value::getOffsetLimit() const { return limit_; } - -std::string Value::toStyledString() const { - StyledWriter writer; - return writer.write(*this); -} - -Value::const_iterator Value::begin() const { - switch (type_) { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if (value_.array_) { - ValueInternalArray::IteratorState it; - value_.array_->makeBeginIterator(it); - return const_iterator(it); - } - break; - case objectValue: - if (value_.map_) { - ValueInternalMap::IteratorState it; - value_.map_->makeBeginIterator(it); - return const_iterator(it); - } - break; -#else - case arrayValue: - case objectValue: - if (value_.map_) - return const_iterator(value_.map_->begin()); - break; -#endif - default: - break; - } - return const_iterator(); -} - -Value::const_iterator Value::end() const { - switch (type_) { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if (value_.array_) { - ValueInternalArray::IteratorState it; - value_.array_->makeEndIterator(it); - return const_iterator(it); - } - break; - case objectValue: - if (value_.map_) { - ValueInternalMap::IteratorState it; - value_.map_->makeEndIterator(it); - return const_iterator(it); - } - break; -#else - case arrayValue: - case objectValue: - if (value_.map_) - return const_iterator(value_.map_->end()); - break; -#endif - default: - break; - } - return const_iterator(); -} - -Value::iterator Value::begin() { - switch (type_) { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if (value_.array_) { - ValueInternalArray::IteratorState it; - value_.array_->makeBeginIterator(it); - return iterator(it); - } - break; - case objectValue: - if (value_.map_) { - ValueInternalMap::IteratorState it; - value_.map_->makeBeginIterator(it); - return iterator(it); - } - break; -#else - case arrayValue: - case objectValue: - if (value_.map_) - return iterator(value_.map_->begin()); - break; -#endif - default: - break; - } - return iterator(); -} - -Value::iterator Value::end() { - switch (type_) { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if (value_.array_) { - ValueInternalArray::IteratorState it; - value_.array_->makeEndIterator(it); - return iterator(it); - } - break; - case objectValue: - if (value_.map_) { - ValueInternalMap::IteratorState it; - value_.map_->makeEndIterator(it); - return iterator(it); - } - break; -#else - case arrayValue: - case objectValue: - if (value_.map_) - return iterator(value_.map_->end()); - break; -#endif - default: - break; - } - return iterator(); -} - -// class PathArgument -// ////////////////////////////////////////////////////////////////// - -PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} - -PathArgument::PathArgument(ArrayIndex index) - : key_(), index_(index), kind_(kindIndex) {} - -PathArgument::PathArgument(const char* key) - : key_(key), index_(), kind_(kindKey) {} - -PathArgument::PathArgument(const std::string& key) - : key_(key.c_str()), index_(), kind_(kindKey) {} - -// class Path -// ////////////////////////////////////////////////////////////////// - -Path::Path(const std::string& path, - const PathArgument& a1, - const PathArgument& a2, - const PathArgument& a3, - const PathArgument& a4, - const PathArgument& a5) { - InArgs in; - in.push_back(&a1); - in.push_back(&a2); - in.push_back(&a3); - in.push_back(&a4); - in.push_back(&a5); - makePath(path, in); -} - -void Path::makePath(const std::string& path, const InArgs& in) { - const char* current = path.c_str(); - const char* end = current + path.length(); - InArgs::const_iterator itInArg = in.begin(); - while (current != end) { - if (*current == '[') { - ++current; - if (*current == '%') - addPathInArg(path, in, itInArg, PathArgument::kindIndex); - else { - ArrayIndex index = 0; - for (; current != end && *current >= '0' && *current <= '9'; ++current) - index = index * 10 + ArrayIndex(*current - '0'); - args_.push_back(index); - } - if (current == end || *current++ != ']') - invalidPath(path, int(current - path.c_str())); - } else if (*current == '%') { - addPathInArg(path, in, itInArg, PathArgument::kindKey); - ++current; - } else if (*current == '.') { - ++current; - } else { - const char* beginName = current; - while (current != end && !strchr("[.", *current)) - ++current; - args_.push_back(std::string(beginName, current)); - } - } -} - -void Path::addPathInArg(const std::string& /*path*/, - const InArgs& in, - InArgs::const_iterator& itInArg, - PathArgument::Kind kind) { - if (itInArg == in.end()) { - // Error: missing argument %d - } else if ((*itInArg)->kind_ != kind) { - // Error: bad argument type - } else { - args_.push_back(**itInArg); - } -} - -void Path::invalidPath(const std::string& /*path*/, int /*location*/) { - // Error: invalid path. -} - -const Value& Path::resolve(const Value& root) const { - const Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray() || !node->isValidIndex(arg.index_)) { - // Error: unable to resolve path (array value expected at position... - } - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) { - // Error: unable to resolve path (object value expected at position...) - } - node = &((*node)[arg.key_]); - if (node == &Value::null) { - // Error: unable to resolve path (object has no member named '' at - // position...) - } - } - } - return *node; -} - -Value Path::resolve(const Value& root, const Value& defaultValue) const { - const Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray() || !node->isValidIndex(arg.index_)) - return defaultValue; - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) - return defaultValue; - node = &((*node)[arg.key_]); - if (node == &Value::null) - return defaultValue; - } - } - return *node; -} - -Value& Path::make(Value& root) const { - Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray()) { - // Error: node is not an array at position ... - } - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) { - // Error: node is not an object at position... - } - node = &((*node)[arg.key_]); - } - } - return *node; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_value.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_writer.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2011 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include -#include "json_tool.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below -#include -#define isfinite _finite -#define snprintf _snprintf -#endif - -#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 -// Disable warning about strdup being deprecated. -#pragma warning(disable : 4996) -#endif - -namespace Json { - -static bool containsControlCharacter(const char* str) { - while (*str) { - if (isControlCharacter(*(str++))) - return true; - } - return false; -} - -std::string valueToString(LargestInt value) { - UIntToStringBuffer buffer; - char* current = buffer + sizeof(buffer); - bool isNegative = value < 0; - if (isNegative) - value = -value; - uintToString(LargestUInt(value), current); - if (isNegative) - *--current = '-'; - assert(current >= buffer); - return current; -} - -std::string valueToString(LargestUInt value) { - UIntToStringBuffer buffer; - char* current = buffer + sizeof(buffer); - uintToString(value, current); - assert(current >= buffer); - return current; -} - -#if defined(JSON_HAS_INT64) - -std::string valueToString(Int value) { - return valueToString(LargestInt(value)); -} - -std::string valueToString(UInt value) { - return valueToString(LargestUInt(value)); -} - -#endif // # if defined(JSON_HAS_INT64) - -std::string valueToString(double value) { - // Allocate a buffer that is more than large enough to store the 16 digits of - // precision requested below. - char buffer[32]; - int len = -1; - -// Print into the buffer. We need not request the alternative representation -// that always has a decimal point because JSON doesn't distingish the -// concepts of reals and integers. -#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with - // visual studio 2005 to - // avoid warning. -#if defined(WINCE) - len = _snprintf(buffer, sizeof(buffer), "%.16g", value); -#else - len = sprintf_s(buffer, sizeof(buffer), "%.16g", value); -#endif -#else - if (isfinite(value)) { - len = snprintf(buffer, sizeof(buffer), "%.16g", value); - } else { - // IEEE standard states that NaN values will not compare to themselves - if (value != value) { - len = snprintf(buffer, sizeof(buffer), "null"); - } else if (value < 0) { - len = snprintf(buffer, sizeof(buffer), "-1e+9999"); - } else { - len = snprintf(buffer, sizeof(buffer), "1e+9999"); - } - // For those, we do not need to call fixNumLoc, but it is fast. - } -#endif - assert(len >= 0); - fixNumericLocale(buffer, buffer + len); - return buffer; -} - -std::string valueToString(bool value) { return value ? "true" : "false"; } - -std::string valueToQuotedString(const char* value) { - if (value == NULL) - return ""; - // Not sure how to handle unicode... - if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && - !containsControlCharacter(value)) - return std::string("\"") + value + "\""; - // We have to walk value and escape any special characters. - // Appending to std::string is not efficient, but this should be rare. - // (Note: forward slashes are *not* rare, but I am not escaping them.) - std::string::size_type maxsize = - strlen(value) * 2 + 3; // allescaped+quotes+NULL - std::string result; - result.reserve(maxsize); // to avoid lots of mallocs - result += "\""; - for (const char* c = value; *c != 0; ++c) { - switch (*c) { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - // case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something. - // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); - result += oss.str(); - } else { - result += *c; - } - break; - } - } - result += "\""; - return result; -} - -// Class Writer -// ////////////////////////////////////////////////////////////////// -Writer::~Writer() {} - -// Class FastWriter -// ////////////////////////////////////////////////////////////////// - -FastWriter::FastWriter() - : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), - omitEndingLineFeed_(false) {} - -void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } - -void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } - -void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } - -std::string FastWriter::write(const Value& root) { - document_ = ""; - writeValue(root); - if (!omitEndingLineFeed_) - document_ += "\n"; - return document_; -} - -void FastWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - if (!dropNullPlaceholders_) - document_ += "null"; - break; - case intValue: - document_ += valueToString(value.asLargestInt()); - break; - case uintValue: - document_ += valueToString(value.asLargestUInt()); - break; - case realValue: - document_ += valueToString(value.asDouble()); - break; - case stringValue: - document_ += valueToQuotedString(value.asCString()); - break; - case booleanValue: - document_ += valueToString(value.asBool()); - break; - case arrayValue: { - document_ += "["; - int size = value.size(); - for (int index = 0; index < size; ++index) { - if (index > 0) - document_ += ","; - writeValue(value[index]); - } - document_ += "]"; - } break; - case objectValue: { - Value::Members members(value.getMemberNames()); - document_ += "{"; - for (Value::Members::iterator it = members.begin(); it != members.end(); - ++it) { - const std::string& name = *it; - if (it != members.begin()) - document_ += ","; - document_ += valueToQuotedString(name.c_str()); - document_ += yamlCompatiblityEnabled_ ? ": " : ":"; - writeValue(value[name]); - } - document_ += "}"; - } break; - } -} - -// Class StyledWriter -// ////////////////////////////////////////////////////////////////// - -StyledWriter::StyledWriter() - : rightMargin_(74), indentSize_(3), addChildValues_() {} - -std::string StyledWriter::write(const Value& root) { - document_ = ""; - addChildValues_ = false; - indentString_ = ""; - writeCommentBeforeValue(root); - writeValue(root); - writeCommentAfterValueOnSameLine(root); - document_ += "\n"; - return document_; -} - -void StyledWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - pushValue("null"); - break; - case intValue: - pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble())); - break; - case stringValue: - pushValue(valueToQuotedString(value.asCString())); - break; - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); - indent(); - Value::Members::iterator it = members.begin(); - for (;;) { - const std::string& name = *it; - const Value& childValue = value[name]; - writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); - document_ += " : "; - writeValue(childValue); - if (++it == members.end()) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - document_ += ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("}"); - } - } break; - } -} - -void StyledWriter::writeArrayValue(const Value& value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isArrayMultiLine = isMultineArray(value); - if (isArrayMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - for (;;) { - const Value& childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - writeIndent(); - writeValue(childValue); - } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - document_ += ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - document_ += "[ "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - document_ += ", "; - document_ += childValues_[index]; - } - document_ += " ]"; - } - } -} - -bool StyledWriter::isMultineArray(const Value& value) { - int size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (int index = 0; index < size && !isMultiLine; ++index) { - const Value& childValue = value[index]; - isMultiLine = - isMultiLine || ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (int index = 0; index < size; ++index) { - writeValue(value[index]); - lineLength += int(childValues_[index].length()); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - -void StyledWriter::pushValue(const std::string& value) { - if (addChildValues_) - childValues_.push_back(value); - else - document_ += value; -} - -void StyledWriter::writeIndent() { - if (!document_.empty()) { - char last = document_[document_.length() - 1]; - if (last == ' ') // already indented - return; - if (last != '\n') // Comments may add new-line - document_ += '\n'; - } - document_ += indentString_; -} - -void StyledWriter::writeWithIndent(const std::string& value) { - writeIndent(); - document_ += value; -} - -void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); } - -void StyledWriter::unindent() { - assert(int(indentString_.size()) >= indentSize_); - indentString_.resize(indentString_.size() - indentSize_); -} - -void StyledWriter::writeCommentBeforeValue(const Value& root) { - if (!root.hasComment(commentBefore)) - return; - - document_ += "\n"; - writeIndent(); - std::string normalizedComment = normalizeEOL(root.getComment(commentBefore)); - std::string::const_iterator iter = normalizedComment.begin(); - while (iter != normalizedComment.end()) { - document_ += *iter; - if (*iter == '\n' && *(iter + 1) == '/') - writeIndent(); - ++iter; - } - - // Comments are stripped of newlines, so add one here - document_ += "\n"; -} - -void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { - if (root.hasComment(commentAfterOnSameLine)) - document_ += " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); - - if (root.hasComment(commentAfter)) { - document_ += "\n"; - document_ += normalizeEOL(root.getComment(commentAfter)); - document_ += "\n"; - } -} - -bool StyledWriter::hasCommentForValue(const Value& value) { - return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); -} - -std::string StyledWriter::normalizeEOL(const std::string& text) { - std::string normalized; - normalized.reserve(text.length()); - const char* begin = text.c_str(); - const char* end = begin + text.length(); - const char* current = begin; - while (current != end) { - char c = *current++; - if (c == '\r') // mac or dos EOL - { - if (*current == '\n') // convert dos EOL - ++current; - normalized += '\n'; - } else // handle unix EOL & other char - normalized += c; - } - return normalized; -} - -// Class StyledStreamWriter -// ////////////////////////////////////////////////////////////////// - -StyledStreamWriter::StyledStreamWriter(std::string indentation) - : document_(NULL), rightMargin_(74), indentation_(indentation), - addChildValues_() {} - -void StyledStreamWriter::write(std::ostream& out, const Value& root) { - document_ = &out; - addChildValues_ = false; - indentString_ = ""; - writeCommentBeforeValue(root); - writeValue(root); - writeCommentAfterValueOnSameLine(root); - *document_ << "\n"; - document_ = NULL; // Forget the stream, for safety. -} - -void StyledStreamWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - pushValue("null"); - break; - case intValue: - pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble())); - break; - case stringValue: - pushValue(valueToQuotedString(value.asCString())); - break; - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); - indent(); - Value::Members::iterator it = members.begin(); - for (;;) { - const std::string& name = *it; - const Value& childValue = value[name]; - writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); - *document_ << " : "; - writeValue(childValue); - if (++it == members.end()) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("}"); - } - } break; - } -} - -void StyledStreamWriter::writeArrayValue(const Value& value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isArrayMultiLine = isMultineArray(value); - if (isArrayMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - for (;;) { - const Value& childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - writeIndent(); - writeValue(childValue); - } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - *document_ << "[ "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - *document_ << ", "; - *document_ << childValues_[index]; - } - *document_ << " ]"; - } - } -} - -bool StyledStreamWriter::isMultineArray(const Value& value) { - int size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (int index = 0; index < size && !isMultiLine; ++index) { - const Value& childValue = value[index]; - isMultiLine = - isMultiLine || ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (int index = 0; index < size; ++index) { - writeValue(value[index]); - lineLength += int(childValues_[index].length()); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - -void StyledStreamWriter::pushValue(const std::string& value) { - if (addChildValues_) - childValues_.push_back(value); - else - *document_ << value; -} - -void StyledStreamWriter::writeIndent() { - /* - Some comments in this method would have been nice. ;-) - - if ( !document_.empty() ) - { - char last = document_[document_.length()-1]; - if ( last == ' ' ) // already indented - return; - if ( last != '\n' ) // Comments may add new-line - *document_ << '\n'; - } - */ - *document_ << '\n' << indentString_; -} - -void StyledStreamWriter::writeWithIndent(const std::string& value) { - writeIndent(); - *document_ << value; -} - -void StyledStreamWriter::indent() { indentString_ += indentation_; } - -void StyledStreamWriter::unindent() { - assert(indentString_.size() >= indentation_.size()); - indentString_.resize(indentString_.size() - indentation_.size()); -} - -void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { - if (!root.hasComment(commentBefore)) - return; - *document_ << normalizeEOL(root.getComment(commentBefore)); - *document_ << "\n"; -} - -void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { - if (root.hasComment(commentAfterOnSameLine)) - *document_ << " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); - - if (root.hasComment(commentAfter)) { - *document_ << "\n"; - *document_ << normalizeEOL(root.getComment(commentAfter)); - *document_ << "\n"; - } -} - -bool StyledStreamWriter::hasCommentForValue(const Value& value) { - return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); -} - -std::string StyledStreamWriter::normalizeEOL(const std::string& text) { - std::string normalized; - normalized.reserve(text.length()); - const char* begin = text.c_str(); - const char* end = begin + text.length(); - const char* current = begin; - while (current != end) { - char c = *current++; - if (c == '\r') // mac or dos EOL - { - if (*current == '\n') // convert dos EOL - ++current; - normalized += '\n'; - } else // handle unix EOL & other char - normalized += c; - } - return normalized; -} - -std::ostream& operator<<(std::ostream& sout, const Value& root) { - Json::StyledStreamWriter writer; - writer.write(sout, root); - return sout; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_writer.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - diff --git a/single/jsoncpp/json.h b/single/jsoncpp/json.h deleted file mode 100644 index 4dfc907..0000000 --- a/single/jsoncpp/json.h +++ /dev/null @@ -1,2016 +0,0 @@ -/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/). -/// It is intented to be used with #include - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -The author (Baptiste Lepilleur) explicitly disclaims copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is -released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur - -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. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - -#ifndef JSON_AMALGATED_H_INCLUDED -# define JSON_AMALGATED_H_INCLUDED -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -#define JSON_IS_AMALGAMATION - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/version.h -// ////////////////////////////////////////////////////////////////////// - -// DO NOT EDIT. This file is generated by CMake from "version" -// and "version.h.in" files. -// Run CMake configure step to update it. -#ifndef JSON_VERSION_H_INCLUDED -# define JSON_VERSION_H_INCLUDED - -# define JSONCPP_VERSION_STRING "0.7.0" -# define JSONCPP_VERSION_MAJOR 0 -# define JSONCPP_VERSION_MINOR 7 -# define JSONCPP_VERSION_PATCH 0 -# define JSONCPP_VERSION_QUALIFIER -# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) - -#endif // JSON_VERSION_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/version.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_CONFIG_H_INCLUDED -#define JSON_CONFIG_H_INCLUDED - -/// If defined, indicates that json library is embedded in CppTL library. -//# define JSON_IN_CPPTL 1 - -/// If defined, indicates that json may leverage CppTL library -//# define JSON_USE_CPPTL 1 -/// If defined, indicates that cpptl vector based map should be used instead of -/// std::map -/// as Value container. -//# define JSON_USE_CPPTL_SMALLMAP 1 -/// If defined, indicates that Json specific container should be used -/// (hash table & simple deque container with customizable allocator). -/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 -//# define JSON_VALUE_USE_INTERNAL_MAP 1 -/// Force usage of standard new/malloc based allocator instead of memory pool -/// based allocator. -/// The memory pools allocator used optimization (initializing Value and -/// ValueInternalLink -/// as if it was a POD) that may cause some validation tool to report errors. -/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. -//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 - -// If non-zero, the library uses exceptions to report bad input instead of C -// assertion macros. The default is to use exceptions. -#ifndef JSON_USE_EXCEPTION -#define JSON_USE_EXCEPTION 1 -#endif - -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgated header. -// #define JSON_IS_AMALGAMATION - -#ifdef JSON_IN_CPPTL -#include -#ifndef JSON_USE_CPPTL -#define JSON_USE_CPPTL 1 -#endif -#endif - -#ifdef JSON_IN_CPPTL -#define JSON_API CPPTL_API -#elif defined(JSON_DLL_BUILD) -#if defined(_MSC_VER) -#define JSON_API __declspec(dllexport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#endif // if defined(_MSC_VER) -#elif defined(JSON_DLL) -#if defined(_MSC_VER) -#define JSON_API __declspec(dllimport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#endif // if defined(_MSC_VER) -#endif // ifdef JSON_IN_CPPTL -#if !defined(JSON_API) -#define JSON_API -#endif - -// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for -// integer -// Storages, and 64 bits integer support is disabled. -// #define JSON_NO_INT64 1 - -#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 -// Microsoft Visual Studio 6 only support conversion from __int64 to double -// (no conversion from unsigned __int64). -#define JSON_USE_INT64_DOUBLE_CONVERSION 1 -// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' -// characters in the debug information) -// All projects I've ever seen with VS6 were using this globally (not bothering -// with pragma push/pop). -#pragma warning(disable : 4786) -#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 - -#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 -/// Indicates that the following function is deprecated. -#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) -#endif - -#if !defined(JSONCPP_DEPRECATED) -#define JSONCPP_DEPRECATED(message) -#endif // if !defined(JSONCPP_DEPRECATED) - -namespace Json { -typedef int Int; -typedef unsigned int UInt; -#if defined(JSON_NO_INT64) -typedef int LargestInt; -typedef unsigned int LargestUInt; -#undef JSON_HAS_INT64 -#else // if defined(JSON_NO_INT64) -// For Microsoft Visual use specific types as long long is not supported -#if defined(_MSC_VER) // Microsoft Visual Studio -typedef __int64 Int64; -typedef unsigned __int64 UInt64; -#else // if defined(_MSC_VER) // Other platforms, use long long -typedef long long int Int64; -typedef unsigned long long int UInt64; -#endif // if defined(_MSC_VER) -typedef Int64 LargestInt; -typedef UInt64 LargestUInt; -#define JSON_HAS_INT64 -#endif // if defined(JSON_NO_INT64) -} // end namespace Json - -#endif // JSON_CONFIG_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_FORWARDS_H_INCLUDED -#define JSON_FORWARDS_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -// writer.h -class FastWriter; -class StyledWriter; - -// reader.h -class Reader; - -// features.h -class Features; - -// value.h -typedef unsigned int ArrayIndex; -class StaticString; -class Path; -class PathArgument; -class Value; -class ValueIteratorBase; -class ValueIterator; -class ValueConstIterator; -#ifdef JSON_VALUE_USE_INTERNAL_MAP -class ValueMapAllocator; -class ValueInternalLink; -class ValueInternalArray; -class ValueInternalMap; -#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - -} // namespace Json - -#endif // JSON_FORWARDS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/features.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_FEATURES_H_INCLUDED -#define CPPTL_JSON_FEATURES_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -/** \brief Configuration passed to reader and writer. - * This configuration object can be used to force the Reader or Writer - * to behave in a standard conforming way. - */ -class JSON_API Features { -public: - /** \brief A configuration that allows all features and assumes all strings - * are UTF-8. - * - C & C++ comments are allowed - * - Root object can be any JSON value - * - Assumes Value strings are encoded in UTF-8 - */ - static Features all(); - - /** \brief A configuration that is strictly compatible with the JSON - * specification. - * - Comments are forbidden. - * - Root object must be either an array or an object value. - * - Assumes Value strings are encoded in UTF-8 - */ - static Features strictMode(); - - /** \brief Initialize the configuration like JsonConfig::allFeatures; - */ - Features(); - - /// \c true if comments are allowed. Default: \c true. - bool allowComments_; - - /// \c true if root must be either an array or an object value. Default: \c - /// false. - bool strictRoot_; - - /// \c true if dropped null placeholders are allowed. Default: \c false. - bool allowDroppedNullPlaceholders_; - - /// \c true if numeric object key are allowed. Default: \c false. - bool allowNumericKeys_; -}; - -} // namespace Json - -#endif // CPPTL_JSON_FEATURES_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/features.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/value.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_H_INCLUDED -#define CPPTL_JSON_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include - -#ifndef JSON_USE_CPPTL_SMALLMAP -#include -#else -#include -#endif -#ifdef JSON_USE_CPPTL -#include -#endif - -// Disable warning C4251: : needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -/** \brief JSON (JavaScript Object Notation). - */ -namespace Json { - -/** \brief Type of the value held by a Value object. - */ -enum ValueType { - nullValue = 0, ///< 'null' value - intValue, ///< signed integer value - uintValue, ///< unsigned integer value - realValue, ///< double value - stringValue, ///< UTF-8 string value - booleanValue, ///< bool value - arrayValue, ///< array value (ordered list) - objectValue ///< object value (collection of name/value pairs). -}; - -enum CommentPlacement { - commentBefore = 0, ///< a comment placed on the line before a value - commentAfterOnSameLine, ///< a comment just after a value on the same line - commentAfter, ///< a comment on the line after a value (only make sense for - /// root value) - numberOfCommentPlacement -}; - -//# ifdef JSON_USE_CPPTL -// typedef CppTL::AnyEnumerator EnumMemberNames; -// typedef CppTL::AnyEnumerator EnumValues; -//# endif - -/** \brief Lightweight wrapper to tag static string. - * - * Value constructor and objectValue member assignement takes advantage of the - * StaticString and avoid the cost of string duplication when storing the - * string or the member name. - * - * Example of usage: - * \code - * Json::Value aValue( StaticString("some text") ); - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ -class JSON_API StaticString { -public: - explicit StaticString(const char* czstring) : str_(czstring) {} - - operator const char*() const { return str_; } - - const char* c_str() const { return str_; } - -private: - const char* str_; -}; - -/** \brief Represents a JSON value. - * - * This class is a discriminated union wrapper that can represents a: - * - signed integer [range: Value::minInt - Value::maxInt] - * - unsigned integer (range: 0 - Value::maxUInt) - * - double - * - UTF-8 string - * - boolean - * - 'null' - * - an ordered list of Value - * - collection of name/value pairs (javascript object) - * - * The type of the held value is represented by a #ValueType and - * can be obtained using type(). - * - * values of an #objectValue or #arrayValue can be accessed using operator[]() - *methods. - * Non const methods will automatically create the a #nullValue element - * if it does not exist. - * The sequence of an #arrayValue will be automatically resize and initialized - * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. - * - * The get() methods can be used to obtanis default value in the case the - *required element - * does not exist. - * - * It is possible to iterate over the list of a #objectValue values using - * the getMemberNames() method. - */ -class JSON_API Value { - friend class ValueIteratorBase; -#ifdef JSON_VALUE_USE_INTERNAL_MAP - friend class ValueInternalLink; - friend class ValueInternalMap; -#endif -public: - typedef std::vector Members; - typedef ValueIterator iterator; - typedef ValueConstIterator const_iterator; - typedef Json::UInt UInt; - typedef Json::Int Int; -#if defined(JSON_HAS_INT64) - typedef Json::UInt64 UInt64; - typedef Json::Int64 Int64; -#endif // defined(JSON_HAS_INT64) - typedef Json::LargestInt LargestInt; - typedef Json::LargestUInt LargestUInt; - typedef Json::ArrayIndex ArrayIndex; - - static const Value& null; - /// Minimum signed integer value that can be stored in a Json::Value. - static const LargestInt minLargestInt; - /// Maximum signed integer value that can be stored in a Json::Value. - static const LargestInt maxLargestInt; - /// Maximum unsigned integer value that can be stored in a Json::Value. - static const LargestUInt maxLargestUInt; - - /// Minimum signed int value that can be stored in a Json::Value. - static const Int minInt; - /// Maximum signed int value that can be stored in a Json::Value. - static const Int maxInt; - /// Maximum unsigned int value that can be stored in a Json::Value. - static const UInt maxUInt; - -#if defined(JSON_HAS_INT64) - /// Minimum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 minInt64; - /// Maximum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 maxInt64; - /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. - static const UInt64 maxUInt64; -#endif // defined(JSON_HAS_INT64) - -private: -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION -#ifndef JSON_VALUE_USE_INTERNAL_MAP - class CZString { - public: - enum DuplicationPolicy { - noDuplication = 0, - duplicate, - duplicateOnCopy - }; - CZString(ArrayIndex index); - CZString(const char* cstr, DuplicationPolicy allocate); - CZString(const CZString& other); - ~CZString(); - CZString& operator=(CZString other); - bool operator<(const CZString& other) const; - bool operator==(const CZString& other) const; - ArrayIndex index() const; - const char* c_str() const; - bool isStaticString() const; - - private: - void swap(CZString& other); - const char* cstr_; - ArrayIndex index_; - }; - -public: -#ifndef JSON_USE_CPPTL_SMALLMAP - typedef std::map ObjectValues; -#else - typedef CppTL::SmallMap ObjectValues; -#endif // ifndef JSON_USE_CPPTL_SMALLMAP -#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP -#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - -public: - /** \brief Create a default Value of the given type. - - This is a very useful constructor. - To create an empty array, pass arrayValue. - To create an empty object, pass objectValue. - Another Value can then be set to this one by assignment. -This is useful since clear() and resize() will not alter types. - - Examples: -\code -Json::Value null_value; // null -Json::Value arr_value(Json::arrayValue); // [] -Json::Value obj_value(Json::objectValue); // {} -\endcode - */ - Value(ValueType type = nullValue); - Value(Int value); - Value(UInt value); -#if defined(JSON_HAS_INT64) - Value(Int64 value); - Value(UInt64 value); -#endif // if defined(JSON_HAS_INT64) - Value(double value); - Value(const char* value); - Value(const char* beginValue, const char* endValue); - /** \brief Constructs a value from a static string. - - * Like other value string constructor but do not duplicate the string for - * internal storage. The given string must remain alive after the call to this - * constructor. - * Example of usage: - * \code - * Json::Value aValue( StaticString("some text") ); - * \endcode - */ - Value(const StaticString& value); - Value(const std::string& value); -#ifdef JSON_USE_CPPTL - Value(const CppTL::ConstString& value); -#endif - Value(bool value); - Value(const Value& other); - ~Value(); - - Value& operator=(Value other); - /// Swap values. - /// \note Currently, comments are intentionally not swapped, for - /// both logic and efficiency. - void swap(Value& other); - - ValueType type() const; - - bool operator<(const Value& other) const; - bool operator<=(const Value& other) const; - bool operator>=(const Value& other) const; - bool operator>(const Value& other) const; - - bool operator==(const Value& other) const; - bool operator!=(const Value& other) const; - - int compare(const Value& other) const; - - const char* asCString() const; - std::string asString() const; -#ifdef JSON_USE_CPPTL - CppTL::ConstString asConstString() const; -#endif - Int asInt() const; - UInt asUInt() const; -#if defined(JSON_HAS_INT64) - Int64 asInt64() const; - UInt64 asUInt64() const; -#endif // if defined(JSON_HAS_INT64) - LargestInt asLargestInt() const; - LargestUInt asLargestUInt() const; - float asFloat() const; - double asDouble() const; - bool asBool() const; - - bool isNull() const; - bool isBool() const; - bool isInt() const; - bool isInt64() const; - bool isUInt() const; - bool isUInt64() const; - bool isIntegral() const; - bool isDouble() const; - bool isNumeric() const; - bool isString() const; - bool isArray() const; - bool isObject() const; - - bool isConvertibleTo(ValueType other) const; - - /// Number of values in array or object - ArrayIndex size() const; - - /// \brief Return true if empty array, empty object, or null; - /// otherwise, false. - bool empty() const; - - /// Return isNull() - bool operator!() const; - - /// Remove all object members and array elements. - /// \pre type() is arrayValue, objectValue, or nullValue - /// \post type() is unchanged - void clear(); - - /// Resize the array to size elements. - /// New elements are initialized to null. - /// May only be called on nullValue or arrayValue. - /// \pre type() is arrayValue or nullValue - /// \post type() is arrayValue - void resize(ArrayIndex size); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are - /// inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value& operator[](ArrayIndex index); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are - /// inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value& operator[](int index); - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value& operator[](ArrayIndex index) const; - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value& operator[](int index) const; - - /// If the array contains at least index+1 elements, returns the element - /// value, - /// otherwise returns defaultValue. - Value get(ArrayIndex index, const Value& defaultValue) const; - /// Return true if index < size(). - bool isValidIndex(ArrayIndex index) const; - /// \brief Append value to array at the end. - /// - /// Equivalent to jsonvalue[jsonvalue.size()] = value; - Value& append(const Value& value); - - /// Access an object value by name, create a null member if it does not exist. - Value& operator[](const char* key); - /// Access an object value by name, returns null if there is no member with - /// that name. - const Value& operator[](const char* key) const; - /// Access an object value by name, create a null member if it does not exist. - Value& operator[](const std::string& key); - /// Access an object value by name, returns null if there is no member with - /// that name. - const Value& operator[](const std::string& key) const; - /** \brief Access an object value by name, create a null member if it does not - exist. - - * If the object as no entry for that name, then the member name used to store - * the new entry is not duplicated. - * Example of use: - * \code - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ - Value& operator[](const StaticString& key); -#ifdef JSON_USE_CPPTL - /// Access an object value by name, create a null member if it does not exist. - Value& operator[](const CppTL::ConstString& key); - /// Access an object value by name, returns null if there is no member with - /// that name. - const Value& operator[](const CppTL::ConstString& key) const; -#endif - /// Return the member named key if it exist, defaultValue otherwise. - Value get(const char* key, const Value& defaultValue) const; - /// Return the member named key if it exist, defaultValue otherwise. - Value get(const std::string& key, const Value& defaultValue) const; -#ifdef JSON_USE_CPPTL - /// Return the member named key if it exist, defaultValue otherwise. - Value get(const CppTL::ConstString& key, const Value& defaultValue) const; -#endif - /// \brief Remove and return the named member. - /// - /// Do nothing if it did not exist. - /// \return the removed Value, or null. - /// \pre type() is objectValue or nullValue - /// \post type() is unchanged - Value removeMember(const char* key); - /// Same as removeMember(const char*) - Value removeMember(const std::string& key); - - /// Return true if the object has a member named key. - bool isMember(const char* key) const; - /// Return true if the object has a member named key. - bool isMember(const std::string& key) const; -#ifdef JSON_USE_CPPTL - /// Return true if the object has a member named key. - bool isMember(const CppTL::ConstString& key) const; -#endif - - /// \brief Return a list of the member names. - /// - /// If null, return an empty list. - /// \pre type() is objectValue or nullValue - /// \post if type() was nullValue, it remains nullValue - Members getMemberNames() const; - - //# ifdef JSON_USE_CPPTL - // EnumMemberNames enumMemberNames() const; - // EnumValues enumValues() const; - //# endif - - /// Comments must be //... or /* ... */ - void setComment(const char* comment, CommentPlacement placement); - /// Comments must be //... or /* ... */ - void setComment(const std::string& comment, CommentPlacement placement); - bool hasComment(CommentPlacement placement) const; - /// Include delimiters and embedded newlines. - std::string getComment(CommentPlacement placement) const; - - std::string toStyledString() const; - - const_iterator begin() const; - const_iterator end() const; - - iterator begin(); - iterator end(); - - // Accessors for the [start, limit) range of bytes within the JSON text from - // which this value was parsed, if any. - void setOffsetStart(size_t start); - void setOffsetLimit(size_t limit); - size_t getOffsetStart() const; - size_t getOffsetLimit() const; - -private: - Value& resolveReference(const char* key, bool isStatic); - -#ifdef JSON_VALUE_USE_INTERNAL_MAP - inline bool isItemAvailable() const { return itemIsUsed_ == 0; } - - inline void setItemUsed(bool isUsed = true) { itemIsUsed_ = isUsed ? 1 : 0; } - - inline bool isMemberNameStatic() const { return memberNameIsStatic_ == 0; } - - inline void setMemberNameIsStatic(bool isStatic) { - memberNameIsStatic_ = isStatic ? 1 : 0; - } -#endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP - -private: - struct CommentInfo { - CommentInfo(); - ~CommentInfo(); - - void setComment(const char* text); - - char* comment_; - }; - - // struct MemberNamesTransform - //{ - // typedef const char *result_type; - // const char *operator()( const CZString &name ) const - // { - // return name.c_str(); - // } - //}; - - union ValueHolder { - LargestInt int_; - LargestUInt uint_; - double real_; - bool bool_; - char* string_; -#ifdef JSON_VALUE_USE_INTERNAL_MAP - ValueInternalArray* array_; - ValueInternalMap* map_; -#else - ObjectValues* map_; -#endif - } value_; - ValueType type_ : 8; - int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. -#ifdef JSON_VALUE_USE_INTERNAL_MAP - unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. - int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. -#endif - CommentInfo* comments_; - - // [start, limit) byte offsets in the source JSON text from which this Value - // was extracted. - size_t start_; - size_t limit_; -}; - -/** \brief Experimental and untested: represents an element of the "path" to - * access a node. - */ -class JSON_API PathArgument { -public: - friend class Path; - - PathArgument(); - PathArgument(ArrayIndex index); - PathArgument(const char* key); - PathArgument(const std::string& key); - -private: - enum Kind { - kindNone = 0, - kindIndex, - kindKey - }; - std::string key_; - ArrayIndex index_; - Kind kind_; -}; - -/** \brief Experimental and untested: represents a "path" to access a node. - * - * Syntax: - * - "." => root node - * - ".[n]" => elements at index 'n' of root node (an array value) - * - ".name" => member named 'name' of root node (an object value) - * - ".name1.name2.name3" - * - ".[0][1][2].name1[3]" - * - ".%" => member name is provided as parameter - * - ".[%]" => index is provied as parameter - */ -class JSON_API Path { -public: - Path(const std::string& path, - const PathArgument& a1 = PathArgument(), - const PathArgument& a2 = PathArgument(), - const PathArgument& a3 = PathArgument(), - const PathArgument& a4 = PathArgument(), - const PathArgument& a5 = PathArgument()); - - const Value& resolve(const Value& root) const; - Value resolve(const Value& root, const Value& defaultValue) const; - /// Creates the "path" to access the specified node and returns a reference on - /// the node. - Value& make(Value& root) const; - -private: - typedef std::vector InArgs; - typedef std::vector Args; - - void makePath(const std::string& path, const InArgs& in); - void addPathInArg(const std::string& path, - const InArgs& in, - InArgs::const_iterator& itInArg, - PathArgument::Kind kind); - void invalidPath(const std::string& path, int location); - - Args args_; -}; - -#ifdef JSON_VALUE_USE_INTERNAL_MAP -/** \brief Allocator to customize Value internal map. - * Below is an example of a simple implementation (default implementation - actually - * use memory pool for speed). - * \code - class DefaultValueMapAllocator : public ValueMapAllocator - { - public: // overridden from ValueMapAllocator - virtual ValueInternalMap *newMap() - { - return new ValueInternalMap(); - } - - virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) - { - return new ValueInternalMap( other ); - } - - virtual void destructMap( ValueInternalMap *map ) - { - delete map; - } - - virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) - { - return new ValueInternalLink[size]; - } - - virtual void releaseMapBuckets( ValueInternalLink *links ) - { - delete [] links; - } - - virtual ValueInternalLink *allocateMapLink() - { - return new ValueInternalLink(); - } - - virtual void releaseMapLink( ValueInternalLink *link ) - { - delete link; - } - }; - * \endcode - */ -class JSON_API ValueMapAllocator { -public: - virtual ~ValueMapAllocator(); - virtual ValueInternalMap* newMap() = 0; - virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) = 0; - virtual void destructMap(ValueInternalMap* map) = 0; - virtual ValueInternalLink* allocateMapBuckets(unsigned int size) = 0; - virtual void releaseMapBuckets(ValueInternalLink* links) = 0; - virtual ValueInternalLink* allocateMapLink() = 0; - virtual void releaseMapLink(ValueInternalLink* link) = 0; -}; - -/** \brief ValueInternalMap hash-map bucket chain link (for internal use only). - * \internal previous_ & next_ allows for bidirectional traversal. - */ -class JSON_API ValueInternalLink { -public: - enum { - itemPerLink = 6 - }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. - enum InternalFlags { - flagAvailable = 0, - flagUsed = 1 - }; - - ValueInternalLink(); - - ~ValueInternalLink(); - - Value items_[itemPerLink]; - char* keys_[itemPerLink]; - ValueInternalLink* previous_; - ValueInternalLink* next_; -}; - -/** \brief A linked page based hash-table implementation used internally by - *Value. - * \internal ValueInternalMap is a tradional bucket based hash-table, with a - *linked - * list in each bucket to handle collision. There is an addional twist in that - * each node of the collision linked list is a page containing a fixed amount of - * value. This provides a better compromise between memory usage and speed. - * - * Each bucket is made up of a chained list of ValueInternalLink. The last - * link of a given bucket can be found in the 'previous_' field of the following - *bucket. - * The last link of the last bucket is stored in tailLink_ as it has no - *following bucket. - * Only the last link of a bucket may contains 'available' item. The last link - *always - * contains at least one element unless is it the bucket one very first link. - */ -class JSON_API ValueInternalMap { - friend class ValueIteratorBase; - friend class Value; - -public: - typedef unsigned int HashKey; - typedef unsigned int BucketIndex; - -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - struct IteratorState { - IteratorState() : map_(0), link_(0), itemIndex_(0), bucketIndex_(0) {} - ValueInternalMap* map_; - ValueInternalLink* link_; - BucketIndex itemIndex_; - BucketIndex bucketIndex_; - }; -#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - - ValueInternalMap(); - ValueInternalMap(const ValueInternalMap& other); - ValueInternalMap& operator=(ValueInternalMap other); - ~ValueInternalMap(); - - void swap(ValueInternalMap& other); - - BucketIndex size() const; - - void clear(); - - bool reserveDelta(BucketIndex growth); - - bool reserve(BucketIndex newItemCount); - - const Value* find(const char* key) const; - - Value* find(const char* key); - - Value& resolveReference(const char* key, bool isStatic); - - void remove(const char* key); - - void doActualRemove(ValueInternalLink* link, - BucketIndex index, - BucketIndex bucketIndex); - - ValueInternalLink*& getLastLinkInBucket(BucketIndex bucketIndex); - - Value& setNewItem(const char* key, - bool isStatic, - ValueInternalLink* link, - BucketIndex index); - - Value& unsafeAdd(const char* key, bool isStatic, HashKey hashedKey); - - HashKey hash(const char* key) const; - - int compare(const ValueInternalMap& other) const; - -private: - void makeBeginIterator(IteratorState& it) const; - void makeEndIterator(IteratorState& it) const; - static bool equals(const IteratorState& x, const IteratorState& other); - static void increment(IteratorState& iterator); - static void incrementBucket(IteratorState& iterator); - static void decrement(IteratorState& iterator); - static const char* key(const IteratorState& iterator); - static const char* key(const IteratorState& iterator, bool& isStatic); - static Value& value(const IteratorState& iterator); - static int distance(const IteratorState& x, const IteratorState& y); - -private: - ValueInternalLink* buckets_; - ValueInternalLink* tailLink_; - BucketIndex bucketsSize_; - BucketIndex itemCount_; -}; - -/** \brief A simplified deque implementation used internally by Value. -* \internal -* It is based on a list of fixed "page", each page contains a fixed number of -*items. -* Instead of using a linked-list, a array of pointer is used for fast item -*look-up. -* Look-up for an element is as follow: -* - compute page index: pageIndex = itemIndex / itemsPerPage -* - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] -* -* Insertion is amortized constant time (only the array containing the index of -*pointers -* need to be reallocated when items are appended). -*/ -class JSON_API ValueInternalArray { - friend class Value; - friend class ValueIteratorBase; - -public: - enum { - itemsPerPage = 8 - }; // should be a power of 2 for fast divide and modulo. - typedef Value::ArrayIndex ArrayIndex; - typedef unsigned int PageIndex; - -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - struct IteratorState // Must be a POD - { - IteratorState() : array_(0), currentPageIndex_(0), currentItemIndex_(0) {} - ValueInternalArray* array_; - Value** currentPageIndex_; - unsigned int currentItemIndex_; - }; -#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - - ValueInternalArray(); - ValueInternalArray(const ValueInternalArray& other); - ValueInternalArray& operator=(ValueInternalArray other); - ~ValueInternalArray(); - void swap(ValueInternalArray& other); - - void clear(); - void resize(ArrayIndex newSize); - - Value& resolveReference(ArrayIndex index); - - Value* find(ArrayIndex index) const; - - ArrayIndex size() const; - - int compare(const ValueInternalArray& other) const; - -private: - static bool equals(const IteratorState& x, const IteratorState& other); - static void increment(IteratorState& iterator); - static void decrement(IteratorState& iterator); - static Value& dereference(const IteratorState& iterator); - static Value& unsafeDereference(const IteratorState& iterator); - static int distance(const IteratorState& x, const IteratorState& y); - static ArrayIndex indexOf(const IteratorState& iterator); - void makeBeginIterator(IteratorState& it) const; - void makeEndIterator(IteratorState& it) const; - void makeIterator(IteratorState& it, ArrayIndex index) const; - - void makeIndexValid(ArrayIndex index); - - Value** pages_; - ArrayIndex size_; - PageIndex pageCount_; -}; - -/** \brief Experimental: do not use. Allocator to customize Value internal -array. - * Below is an example of a simple implementation (actual implementation use - * memory pool). - \code -class DefaultValueArrayAllocator : public ValueArrayAllocator -{ -public: // overridden from ValueArrayAllocator -virtual ~DefaultValueArrayAllocator() -{ -} - -virtual ValueInternalArray *newArray() -{ - return new ValueInternalArray(); -} - -virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) -{ - return new ValueInternalArray( other ); -} - -virtual void destruct( ValueInternalArray *array ) -{ - delete array; -} - -virtual void reallocateArrayPageIndex( Value **&indexes, - ValueInternalArray::PageIndex -&indexCount, - ValueInternalArray::PageIndex -minNewIndexCount ) -{ - ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; - if ( minNewIndexCount > newIndexCount ) - newIndexCount = minNewIndexCount; - void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); - if ( !newIndexes ) - throw std::bad_alloc(); - indexCount = newIndexCount; - indexes = static_cast( newIndexes ); -} -virtual void releaseArrayPageIndex( Value **indexes, - ValueInternalArray::PageIndex indexCount ) -{ - if ( indexes ) - free( indexes ); -} - -virtual Value *allocateArrayPage() -{ - return static_cast( malloc( sizeof(Value) * -ValueInternalArray::itemsPerPage ) ); -} - -virtual void releaseArrayPage( Value *value ) -{ - if ( value ) - free( value ); -} -}; - \endcode - */ -class JSON_API ValueArrayAllocator { -public: - virtual ~ValueArrayAllocator(); - virtual ValueInternalArray* newArray() = 0; - virtual ValueInternalArray* newArrayCopy(const ValueInternalArray& other) = 0; - virtual void destructArray(ValueInternalArray* array) = 0; - /** \brief Reallocate array page index. - * Reallocates an array of pointer on each page. - * \param indexes [input] pointer on the current index. May be \c NULL. - * [output] pointer on the new index of at least - * \a minNewIndexCount pages. - * \param indexCount [input] current number of pages in the index. - * [output] number of page the reallocated index can handle. - * \b MUST be >= \a minNewIndexCount. - * \param minNewIndexCount Minimum number of page the new index must be able - * to - * handle. - */ - virtual void - reallocateArrayPageIndex(Value**& indexes, - ValueInternalArray::PageIndex& indexCount, - ValueInternalArray::PageIndex minNewIndexCount) = 0; - virtual void - releaseArrayPageIndex(Value** indexes, - ValueInternalArray::PageIndex indexCount) = 0; - virtual Value* allocateArrayPage() = 0; - virtual void releaseArrayPage(Value* value) = 0; -}; -#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - -/** \brief base class for Value iterators. - * - */ -class JSON_API ValueIteratorBase { -public: - typedef std::bidirectional_iterator_tag iterator_category; - typedef unsigned int size_t; - typedef int difference_type; - typedef ValueIteratorBase SelfType; - - ValueIteratorBase(); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); -#else - ValueIteratorBase(const ValueInternalArray::IteratorState& state); - ValueIteratorBase(const ValueInternalMap::IteratorState& state); -#endif - - bool operator==(const SelfType& other) const { return isEqual(other); } - - bool operator!=(const SelfType& other) const { return !isEqual(other); } - - difference_type operator-(const SelfType& other) const { - return computeDistance(other); - } - - /// Return either the index or the member name of the referenced value as a - /// Value. - Value key() const; - - /// Return the index of the referenced Value. -1 if it is not an arrayValue. - UInt index() const; - - /// Return the member name of the referenced Value. "" if it is not an - /// objectValue. - const char* memberName() const; - -protected: - Value& deref() const; - - void increment(); - - void decrement(); - - difference_type computeDistance(const SelfType& other) const; - - bool isEqual(const SelfType& other) const; - - void copy(const SelfType& other); - -private: -#ifndef JSON_VALUE_USE_INTERNAL_MAP - Value::ObjectValues::iterator current_; - // Indicates that iterator is for a null value. - bool isNull_; -#else - union { - ValueInternalArray::IteratorState array_; - ValueInternalMap::IteratorState map_; - } iterator_; - bool isArray_; -#endif -}; - -/** \brief const iterator for object and array value. - * - */ -class JSON_API ValueConstIterator : public ValueIteratorBase { - friend class Value; - -public: - typedef const Value value_type; - typedef unsigned int size_t; - typedef int difference_type; - typedef const Value& reference; - typedef const Value* pointer; - typedef ValueConstIterator SelfType; - - ValueConstIterator(); - -private: -/*! \internal Use by Value to create an iterator. - */ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueConstIterator(const Value::ObjectValues::iterator& current); -#else - ValueConstIterator(const ValueInternalArray::IteratorState& state); - ValueConstIterator(const ValueInternalMap::IteratorState& state); -#endif -public: - SelfType& operator=(const ValueIteratorBase& other); - - SelfType operator++(int) { - SelfType temp(*this); - ++*this; - return temp; - } - - SelfType operator--(int) { - SelfType temp(*this); - --*this; - return temp; - } - - SelfType& operator--() { - decrement(); - return *this; - } - - SelfType& operator++() { - increment(); - return *this; - } - - reference operator*() const { return deref(); } - - pointer operator->() const { return &deref(); } -}; - -/** \brief Iterator for object and array value. - */ -class JSON_API ValueIterator : public ValueIteratorBase { - friend class Value; - -public: - typedef Value value_type; - typedef unsigned int size_t; - typedef int difference_type; - typedef Value& reference; - typedef Value* pointer; - typedef ValueIterator SelfType; - - ValueIterator(); - ValueIterator(const ValueConstIterator& other); - ValueIterator(const ValueIterator& other); - -private: -/*! \internal Use by Value to create an iterator. - */ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueIterator(const Value::ObjectValues::iterator& current); -#else - ValueIterator(const ValueInternalArray::IteratorState& state); - ValueIterator(const ValueInternalMap::IteratorState& state); -#endif -public: - SelfType& operator=(const SelfType& other); - - SelfType operator++(int) { - SelfType temp(*this); - ++*this; - return temp; - } - - SelfType operator--(int) { - SelfType temp(*this); - --*this; - return temp; - } - - SelfType& operator--() { - decrement(); - return *this; - } - - SelfType& operator++() { - increment(); - return *this; - } - - reference operator*() const { return deref(); } - - pointer operator->() const { return &deref(); } -}; - -} // namespace Json - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // CPPTL_JSON_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/value.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/reader.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_READER_H_INCLUDED -#define CPPTL_JSON_READER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "features.h" -#include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include - -// Disable warning C4251: : needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -namespace Json { - -/** \brief Unserialize a JSON document into a - *Value. - * - */ -class JSON_API Reader { -public: - typedef char Char; - typedef const Char* Location; - - /** \brief An error tagged with where in the JSON text it was encountered. - * - * The offsets give the [start, limit) range of bytes within the text. Note - * that this is bytes, not codepoints. - * - */ - struct StructuredError { - size_t offset_start; - size_t offset_limit; - std::string message; - }; - - /** \brief Constructs a Reader allowing all features - * for parsing. - */ - Reader(); - - /** \brief Constructs a Reader allowing the specified feature set - * for parsing. - */ - Reader(const Features& features); - - /** \brief Read a Value from a JSON - * document. - * \param document UTF-8 encoded string containing the document to read. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them - * back during - * serialization, \c false to discard comments. - * This parameter is ignored if - * Features::allowComments_ - * is \c false. - * \return \c true if the document was successfully parsed, \c false if an - * error occurred. - */ - bool - parse(const std::string& document, Value& root, bool collectComments = true); - - /** \brief Read a Value from a JSON - document. - * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the - document to read. - * \param endDoc Pointer on the end of the UTF-8 encoded string of the - document to read. - \ Must be >= beginDoc. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them - back during - * serialization, \c false to discard comments. - * This parameter is ignored if - Features::allowComments_ - * is \c false. - * \return \c true if the document was successfully parsed, \c false if an - error occurred. - */ - bool parse(const char* beginDoc, - const char* endDoc, - Value& root, - bool collectComments = true); - - /// \brief Parse from input stream. - /// \see Json::operator>>(std::istream&, Json::Value&). - bool parse(std::istream& is, Value& root, bool collectComments = true); - - /** \brief Returns a user friendly string that list errors in the parsed - * document. - * \return Formatted error message with the list of errors with their location - * in - * the parsed document. An empty string is returned if no error - * occurred - * during parsing. - * \deprecated Use getFormattedErrorMessages() instead (typo fix). - */ - JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") - std::string getFormatedErrorMessages() const; - - /** \brief Returns a user friendly string that list errors in the parsed - * document. - * \return Formatted error message with the list of errors with their location - * in - * the parsed document. An empty string is returned if no error - * occurred - * during parsing. - */ - std::string getFormattedErrorMessages() const; - - /** \brief Returns a vector of structured erros encounted while parsing. - * \return A (possibly empty) vector of StructuredError objects. Currently - * only one error can be returned, but the caller should tolerate - * multiple - * errors. This can occur if the parser recovers from a non-fatal - * parse error and then encounters additional errors. - */ - std::vector getStructuredErrors() const; - -private: - enum TokenType { - tokenEndOfStream = 0, - tokenObjectBegin, - tokenObjectEnd, - tokenArrayBegin, - tokenArrayEnd, - tokenString, - tokenNumber, - tokenTrue, - tokenFalse, - tokenNull, - tokenArraySeparator, - tokenMemberSeparator, - tokenComment, - tokenError - }; - - class Token { - public: - TokenType type_; - Location start_; - Location end_; - }; - - class ErrorInfo { - public: - Token token_; - std::string message_; - Location extra_; - }; - - typedef std::deque Errors; - - bool expectToken(TokenType type, Token& token, const char* message); - bool readToken(Token& token); - void skipSpaces(); - bool match(Location pattern, int patternLength); - bool readComment(); - bool readCStyleComment(); - bool readCppStyleComment(); - bool readString(); - void readNumber(); - bool readValue(); - bool readObject(Token& token); - bool readArray(Token& token); - bool decodeNumber(Token& token); - bool decodeNumber(Token& token, Value& decoded); - bool decodeString(Token& token); - bool decodeString(Token& token, std::string& decoded); - bool decodeDouble(Token& token); - bool decodeDouble(Token& token, Value& decoded); - bool decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode); - bool decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& unicode); - bool addError(const std::string& message, Token& token, Location extra = 0); - bool recoverFromError(TokenType skipUntilToken); - bool addErrorAndRecover(const std::string& message, - Token& token, - TokenType skipUntilToken); - void skipUntilSpace(); - Value& currentValue(); - Char getNextChar(); - void - getLocationLineAndColumn(Location location, int& line, int& column) const; - std::string getLocationLineAndColumn(Location location) const; - void addComment(Location begin, Location end, CommentPlacement placement); - void skipCommentTokens(Token& token); - - typedef std::stack Nodes; - Nodes nodes_; - Errors errors_; - std::string document_; - Location begin_; - Location end_; - Location current_; - Location lastValueEnd_; - Value* lastValue_; - std::string commentsBefore_; - Features features_; - bool collectComments_; -}; - -/** \brief Read from 'sin' into 'root'. - - Always keep comments from the input JSON. - - This can be used to read a file into a particular sub-object. - For example: - \code - Json::Value root; - cin >> root["dir"]["file"]; - cout << root; - \endcode - Result: - \verbatim - { - "dir": { - "file": { - // The input stream JSON would be nested here. - } - } - } - \endverbatim - \throw std::exception on parse error. - \see Json::operator<<() -*/ -JSON_API std::istream& operator>>(std::istream&, Value&); - -} // namespace Json - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // CPPTL_JSON_READER_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/reader.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/writer.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_WRITER_H_INCLUDED -#define JSON_WRITER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include - -// Disable warning C4251: : needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -namespace Json { - -class Value; - -/** \brief Abstract class for writers. - */ -class JSON_API Writer { -public: - virtual ~Writer(); - - virtual std::string write(const Value& root) = 0; -}; - -/** \brief Outputs a Value in JSON format - *without formatting (not human friendly). - * - * The JSON document is written in a single line. It is not intended for 'human' - *consumption, - * but may be usefull to support feature such as RPC where bandwith is limited. - * \sa Reader, Value - */ -class JSON_API FastWriter : public Writer { -public: - FastWriter(); - virtual ~FastWriter() {} - - void enableYAMLCompatibility(); - - /** \brief Drop the "null" string from the writer's output for nullValues. - * Strictly speaking, this is not valid JSON. But when the output is being - * fed to a browser's Javascript, it makes for smaller output and the - * browser can handle the output just fine. - */ - void dropNullPlaceholders(); - - void omitEndingLineFeed(); - -public: // overridden from Writer - virtual std::string write(const Value& root); - -private: - void writeValue(const Value& value); - - std::string document_; - bool yamlCompatiblityEnabled_; - bool dropNullPlaceholders_; - bool omitEndingLineFeed_; -}; - -/** \brief Writes a Value in JSON format in a - *human friendly way. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per - *line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value - *types, - * and all the values fit on one lines, then print the array on a single - *line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their - *#CommentPlacement. - * - * \sa Reader, Value, Value::setComment() - */ -class JSON_API StyledWriter : public Writer { -public: - StyledWriter(); - virtual ~StyledWriter() {} - -public: // overridden from Writer - /** \brief Serialize a Value in JSON format. - * \param root Value to serialize. - * \return String containing the JSON document that represents the root value. - */ - virtual std::string write(const Value& root); - -private: - void writeValue(const Value& value); - void writeArrayValue(const Value& value); - bool isMultineArray(const Value& value); - void pushValue(const std::string& value); - void writeIndent(); - void writeWithIndent(const std::string& value); - void indent(); - void unindent(); - void writeCommentBeforeValue(const Value& root); - void writeCommentAfterValueOnSameLine(const Value& root); - bool hasCommentForValue(const Value& value); - static std::string normalizeEOL(const std::string& text); - - typedef std::vector ChildValues; - - ChildValues childValues_; - std::string document_; - std::string indentString_; - int rightMargin_; - int indentSize_; - bool addChildValues_; -}; - -/** \brief Writes a Value in JSON format in a - human friendly way, - to a stream rather than to a string. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per - line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value - types, - * and all the values fit on one lines, then print the array on a single - line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their - #CommentPlacement. - * - * \param indentation Each level will be indented by this amount extra. - * \sa Reader, Value, Value::setComment() - */ -class JSON_API StyledStreamWriter { -public: - StyledStreamWriter(std::string indentation = "\t"); - ~StyledStreamWriter() {} - -public: - /** \brief Serialize a Value in JSON format. - * \param out Stream to write to. (Can be ostringstream, e.g.) - * \param root Value to serialize. - * \note There is no point in deriving from Writer, since write() should not - * return a value. - */ - void write(std::ostream& out, const Value& root); - -private: - void writeValue(const Value& value); - void writeArrayValue(const Value& value); - bool isMultineArray(const Value& value); - void pushValue(const std::string& value); - void writeIndent(); - void writeWithIndent(const std::string& value); - void indent(); - void unindent(); - void writeCommentBeforeValue(const Value& root); - void writeCommentAfterValueOnSameLine(const Value& root); - bool hasCommentForValue(const Value& value); - static std::string normalizeEOL(const std::string& text); - - typedef std::vector ChildValues; - - ChildValues childValues_; - std::ostream* document_; - std::string indentString_; - int rightMargin_; - std::string indentation_; - bool addChildValues_; -}; - -#if defined(JSON_HAS_INT64) -std::string JSON_API valueToString(Int value); -std::string JSON_API valueToString(UInt value); -#endif // if defined(JSON_HAS_INT64) -std::string JSON_API valueToString(LargestInt value); -std::string JSON_API valueToString(LargestUInt value); -std::string JSON_API valueToString(double value); -std::string JSON_API valueToString(bool value); -std::string JSON_API valueToQuotedString(const char* value); - -/// \brief Output using the StyledStreamWriter. -/// \see Json::operator>>() -JSON_API std::ostream& operator<<(std::ostream&, const Value& root); - -} // namespace Json - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // JSON_WRITER_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/writer.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/assertions.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED -#define CPPTL_JSON_ASSERTIONS_H_INCLUDED - -#include - -#if !defined(JSON_IS_AMALGAMATION) -#include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -#if JSON_USE_EXCEPTION -#include -#define JSON_ASSERT(condition) \ - assert(condition); // @todo <= change this into an exception throw -#define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message); -#else // JSON_USE_EXCEPTION -#define JSON_ASSERT(condition) assert(condition); - -// The call to assert() will show the failure message in debug builds. In -// release bugs we write to invalid memory in order to crash hard, so that a -// debugger or crash reporter gets the chance to take over. We still call exit() -// afterward in order to tell the compiler that this macro doesn't return. -#define JSON_FAIL_MESSAGE(message) \ - { \ - assert(false&& message); \ - strcpy(reinterpret_cast(666), message); \ - exit(123); \ - } - -#endif - -#define JSON_ASSERT_MESSAGE(condition, message) \ - if (!(condition)) { \ - JSON_FAIL_MESSAGE(message) \ - } - -#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/assertions.h -// ////////////////////////////////////////////////////////////////////// - - - - - -#endif //ifndef JSON_AMALGATED_H_INCLUDED - -#ifndef INCLUDE_CPP -#define INCLUDE_CPP -#include "../jsoncpp.cpp" -#endif \ No newline at end of file diff --git a/single/makefile b/single/makefile deleted file mode 100644 index 573b592..0000000 --- a/single/makefile +++ /dev/null @@ -1,18 +0,0 @@ -#gccdir = D:\\Program\\mingw\\x86_64-4.8.2-posix-seh-rt_v3-rev4\\mingw64\\bin\\ -cc = $(gccdir)gcc -cxx = $(gccdir)g++ - -.PHONY: all clean - -all: test.exe - -clean: - del smain.cc - del test.exe - -smain.cc: merge.py jmain.cc reversi.h reversi.cc pattern.h pattern.cc data\\data.h data\\data.cc - py -3 merge.py jmain.cc smain.cc - type data\data.cc >> smain.cc - -test.exe: smain.cc - $(cxx) -O2 -std=c++11 -x c++ smain.cc -o test \ No newline at end of file diff --git a/tcl/test.tcl b/tcl/test.tcl deleted file mode 100644 index e1cd72f..0000000 --- a/tcl/test.tcl +++ /dev/null @@ -1,3 +0,0 @@ -grp_load "python/ptn_rnd_d0s5n10000.dat" 0 100 -use_ptn 0 -set mthd_default $mthd_ptn \ No newline at end of file diff --git a/tree.cc b/tree.cc deleted file mode 100644 index b9628ef..0000000 --- a/tree.cc +++ /dev/null @@ -1,204 +0,0 @@ -#include -#include -#include -#include - -#include "tree.h" -#include "reversi.h" - -void tree::load(const string& path){ - #define _READ(var) fin.read((char *)(&var),sizeof(var)) - - ifstream fin(path,ios::in | ios::binary); - int data_size; - - if(!fin){ - fin.close(); - cout << "Error: Cannot open the file: " << path << " ." << endl; - return; - } - - _READ(data_size); - _READ(this->count); - - if(data_size != sizeof(data)){ - fin.close(); - cout << "Error: The size of data does not match." << endl; - return; - } - - this->destroy(root); - - data dat; - bool flag_child,flag_sibling; - stack storage; - node* ptr; - - _READ(dat); - _READ(flag_child); - _READ(flag_sibling); - root = new node({dat,NULL,NULL,NULL}); - ptr = root; - - while(true){ - while(flag_child){ - if(flag_sibling){ - storage.push(ptr); - } - _READ(dat); - _READ(flag_child); - _READ(flag_sibling); - ptr->child = new node({dat,ptr,NULL,NULL}); - ptr = ptr->child; - } - if(flag_sibling){ - storage.push(ptr); - } - if(storage.empty()){ - break; - } - ptr = storage.top(); - storage.pop(); - _READ(dat); - _READ(flag_child); - _READ(flag_sibling); - ptr->sibling = new node({dat,ptr->parent,NULL,NULL}); - ptr = ptr->sibling; - } - - fin.close(); - #undef _READ -} - -void tree::save(const string& path){ - #define WRITE(var) fout.write((char *)(&var),sizeof(var)) - ofstream fout(path,ios::out | ios::binary); - - int data_size = sizeof(data); - - WRITE(data_size); - WRITE(this->count); - - save(fout,root); - - fout.close(); - #undef WRITE -} - -void tree::save(ostream& out,const node* const& ptr){ - #define WRITE(var) out.write((char *)(&var),sizeof(var)) - - if(ptr){ - bool flag_child = (ptr->child != NULL); - bool flag_sibling = (ptr->sibling != NULL); - - WRITE(ptr->dat); - WRITE(flag_child); - WRITE(flag_sibling); - - save(out,ptr->child); - save(out,ptr->sibling); - } - - #undef WRITE -} - -node* tree::descend(board& brd){ - node* ptr = this->root; - vector vec; - vector param; - - while(ptr->child){ - if(ptr->dat.color){ - for(ptr = ptr->child;ptr;ptr = ptr->sibling){ - vec.push_back(ptr); - param.push_back(float(ptr->dat.win + 5) / (ptr->dat.win + ptr->dat.lose + 10)); - } - }else{ - for(ptr = ptr->child;ptr;ptr = ptr->sibling){ - vec.push_back(ptr); - param.push_back(float(ptr->dat.lose + 5) / (ptr->dat.win + ptr->dat.lose + 10)); - } - } - discrete_distribution selector(param.begin(),param.end()); - ptr = vec[selector(engine)]; - brd.flip(ptr->parent->dat.color,ptr->dat.pos); - // cout << "color: " << ptr->parent->dat.color << endl; - // cout << "x: " << (ptr->dat.pos & 7) << " y: " << (ptr->dat.pos >> 3) << endl; - // brd.print(); - vec.clear(); - param.clear(); - } - return ptr; -} - -#ifdef USE_ASM - #define trail_zero_count(brd,result) \ - asm_tzcnt(brd,result) -#else - #define trail_zero_count(brd,result) \ - result = count(~brd & (brd - 1)) -#endif - -void tree::grow(cmethod mthd,cshort height){ - board brd; - coordinate pos1,pos2; - - brd.initial(); - node* ptr = descend(brd); - - bool flag = false, flag_next = false, color = ptr->dat.color; - board brd_save = brd; - - do{ - flag_next = flag; - flag = brd.play(mthd,color,height).x >= 0; - color = !color; - }while(flag || flag_next); - - calc_type diff = brd.count(true) - brd.count(false); - - if(ptr->dat.win + ptr->dat.lose >= threshold - 2){ - node* ptr_next = ptr; - brd = brd_save; - brd_type brd_move = brd.get_move(color); - brd_type pos; - bool flag_first = true; - - trail_zero_count(brd_move,pos); - while(brd_move){ - brd.flip(ptr->dat.color,pos); - flag = (brd.count_move(!ptr->dat.color) > 0) ^ ptr->dat.color; - - if(flag_first){ - ptr_next->child = new node({{flag,short(pos),0,0},ptr,NULL,NULL}); - ptr_next = ptr_next->child; - }else{ - ptr_next->sibling = new node({{flag,short(pos),0,0},ptr,NULL,NULL}); - ptr_next = ptr_next->sibling; - } - flag_first = false; - brd = brd_save; - brd_move &= brd_move - 1; - trail_zero_count(brd_move,pos); - } - } - - // if(diff == 0){ - // while(ptr){ - // ++ptr->dat.draw; - // ptr = ptr->parent; - // } - // }else - if(diff > 0){ - while(ptr){ - ++ptr->dat.win; - ptr = ptr->parent; - } - }else if(diff < 0){ - while(ptr){ - ++ptr->dat.lose; - ptr = ptr->parent; - } - } -} diff --git a/tree.h b/tree.h deleted file mode 100644 index 13244e6..0000000 --- a/tree.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef TREE_H -#define TREE_H - -#include -#include -#include - -#include "type.h" - -struct data; -struct node; - -struct data{ - bool color; - pos_type pos; - int win; - int lose; -}; - -struct node{ - data dat; - node* parent; - node* sibling; - node* child; -}; - -typedef node* pnode; -typedef const pnode& cpnode; - -class tree{ -public: - node* root; - - tree():count(0){ - root = new node({{true,-1,0,0},NULL,NULL,NULL}); - } - ~tree(){ - destroy(root); - } - - static const int threshold = 10; - - void print()const{ - print(root); - } - - void save(const string& path); - void load(const string& path); - - node* descend(board& brd); - - void grow(cmethod mthd,cshort height); - -private: - int count; - - static void destroy(node*& ptr){ - if(ptr){ - destroy(ptr->sibling); - destroy(ptr->child); - delete ptr; - } - } - - static void print(const node* const& ptr){ - cout<< "((" << ptr->dat.color << "," << ptr->dat.pos << "," - << ptr->dat.win << "," << ptr->dat.lose << ")," - << (ptr->child != NULL) << "," - << (ptr->sibling != NULL) << ")" << endl; - - if(ptr->child){ - print(ptr->child); - } - if(ptr->sibling){ - print(ptr->sibling); - } - } - - static void save(ostream& out,const node* const& ptr); -}; - -#endif //TREE_H \ No newline at end of file diff --git a/type.cc b/type.cc deleted file mode 100644 index 5803bbb..0000000 --- a/type.cc +++ /dev/null @@ -1,9 +0,0 @@ -#include "type.h" - -default_random_engine engine( - chrono::system_clock::now().time_since_epoch().count() -); - -#ifdef DEBUG_SEARCH - ofstream out; -#endif \ No newline at end of file diff --git a/wxsmith/reversi_guiframe.wxs b/wxsmith/reversi_guiframe.wxs deleted file mode 100644 index 2ac67bb..0000000 --- a/wxsmith/reversi_guiframe.wxs +++ /dev/null @@ -1,581 +0,0 @@ - - - - Reversi - image\Reversi.bmp - 0 - - - - wxSYS_COLOUR_BACKGROUND - - - - wxVERTICAL - - - 424,424 - #2B9B00 - - - - - wxALL - 5 - - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - wxVERTICAL - - - - 154,51 - #C8C8C8 - - 26 - - bold - 0 - swiss - Segoe Script - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - 448,296 - - 12 - - bold - 0 - swiss - Consolas - - - - 424,424 - #C8C8C8 - #202020 - - - wxVERTICAL - - - - - - 163,22 - #C8C8C8 - - 14 - - bold - 0 - swiss - Consolas - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - - - Human - Computer - Other Program - - 0 - #202020 - #C8C8C8 - - 14 - - bold - 0 - swiss - Consolas - - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - - - - Irius offline - 332,30 - #C8C8C8 - - 14 - - bold - 0 - swiss - Consolas - - - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - - image\folder_small.png - 32,29 - wxSYS_COLOUR_BACKGROUND - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - - - - - 163,22 - #C8C8C8 - - 14 - - bold - 0 - swiss - Consolas - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - - - Human - Computer - Other Program - - 1 - #202020 - #C8C8C8 - - 14 - - bold - 0 - swiss - Consolas - - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - - - - Irius offline - 332,30 - #C8C8C8 - - 14 - - bold - 0 - swiss - Consolas - - - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - - image\folder_small.png - 32,29 - wxSYS_COLOUR_BACKGROUND - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - - - - - #202020 - #C8C8C8 - - 14 - - bold - 0 - swiss - Consolas - - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL - 5 - - - - - - - - - #C8C8C8 - #202020 - - 14 - - bold - 0 - swiss - Consolas - - - - - - - - #C8C8C8 - #202020 - - 14 - - bold - 0 - swiss - Consolas - - - - - - - - - - book_tree - - - - book_tree - - - #C8C8C8 - #202020 - - 14 - - bold - 0 - swiss - Consolas - - - - - - wxALL|wxEXPAND - 5 - - - - - 266,30 - #C8C8C8 - #202020 - - 14 - - bold - 0 - swiss - Consolas - - - - - wxALL|wxEXPAND - 5 - - - wxALL|wxEXPAND - 5 - - - - - wxALL|wxEXPAND - 5 - - - - - - - - - Start a new game. - - - - - Ctrl-L - Load and execute a script. - - - - - Ctrl-S - - - - Alt-F4 - Quit the application. - - - - - - - - Ctrl-Z - Undo the latest change. - - - - - Ctrl-Y - Redo the latest change. - - - - - - - Alt+H - - - - - Alt+V - - - - - Alt+R - - - - - Alt+C - - - - - Alt+T - - - - - Alt+S - - - - - - Ctrl+E - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - 1 - - 1 - - - - 1 - - 1 - - - - 1 - - 1 - - - - 1 - - 1 - - - - 1 - - 1 - - - - - 1 - - - - 1 - - 1 - - - - - 1 - - - - - - - - 1 - - - - - 1 - - - - - 1 - - - - - 1 - - - - - 1 - - - - - 1 - - - - - 1 - - - - 1 - - 1 - - - - - 1 - - - - - 1 - - - - - - - - F1 - Show info about this application. - - - - - - 1 - -1 - wxSB_NORMAL - - -