diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af2ea1b9..0e8cf79f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,16 +4,32 @@ on: push: pull_request: +env: + WX_VERSION: '3.2.4' + DEFAULT_BRANCH: develop + + jobs: build-on-ubuntu: runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.TOKEN_GITHUB }} + steps: - name: Setup cmake - uses: jwlawson/actions-setup-cmake@v1.12 + uses: jwlawson/actions-setup-cmake@v2 with: cmake-version: '3.24.x' - - name: Test cmake version - run: cmake --version + - name: Checkout + uses: actions/checkout@v4 + with: + path: wex + + - name: Set relative paths + run: | + WXMSW3=$HOME/wx-$WX_VERSION + echo "WXMSW3=$WXMSW3" >> $GITHUB_ENV + - name: Install OS dependencies run: | sudo apt-get update --fix-missing @@ -27,30 +43,65 @@ jobs: libgtk2.0-dev \ mesa-common-dev \ unzip - - name: Get GCC version - run: gcc --version - - name: Get libc version - run: ldd --version + + - name: Get cached build of wxWidgets + uses: actions/cache@v4 + id: cachedwx + with: + path: ${{env.WXMSW3}}/ + key: wxWidgets-${{ env.WX_VERSION }}-linux - name: Install wxWidgets + if: steps.cachedwx.outputs.cache-hit != 'true' run: | - sudo apt-get install -y libwxgtk*-dev - sudo ln -s $(which wx-config) /usr/local/bin/wx-config-3 - wx-config-3 --cflags | grep I + curl -L https://github.com/wxWidgets/wxWidgets/releases/download/v$WX_VERSION/wxWidgets-$WX_VERSION.tar.bz2 -o wxWidgets-$WX_VERSION.tar.bz2 + tar jxf wxWidgets-$WX_VERSION.tar.bz2 + cd wxWidgets-$WX_VERSION + ./configure --prefix=$HOME/wx-$WX_VERSION --enable-shared=no --enable-debug=no --with-gtk=2 --with-libjpeg=builtin --with-libpng=builtin --with-regex=builtin --with-libtiff=builtin --with-zlib=builtin --with-expat=builtin --without-libjbig --without-liblzma --without-gtkprint --with-libnotify=no --with-libmspack=no --with-gnomevfs=no --with-opengl=yes --with-sdl=no --with-cxx=11 + make -j4 + make install + sudo ln -s $HOME/wx-$WX_VERSION/bin/wx-config /usr/local/bin/wx-config-3 + wx-config-3 --cflags + echo $HOME/wx-$WX_VERSION/bin >> $GITHUB_PATH - - name: Get git ref of sibling dependency LK + - name: Save wxWidgets build + if: steps.cachedwx.outputs.cache-hit != 'true' + uses: actions/upload-artifact@v4 + with: + name: wxWidgets-${{ env.WX_VERSION }}-linux + path: | + ${{ env.WXMSW3 }} + + - name: Get branch name for pull request + if: ${{ github.event_name == 'pull_request' }} + run: | + echo "GIT_BRANCH=$GITHUB_BASE_REF" >> $GITHUB_ENV + + - name: Get branch name for push + if: ${{ github.event_name == 'push' }} + run: | + echo "GIT_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV + + - name: Determine branches for other repos + shell: bash {0} run: | - ref=$(git ls-remote --exit-code git://github.com/NREL/lk.git refs/heads/develop | awk '{print $1}') + git ls-remote --heads --exit-code https://github.com/NREL/lk.git $GIT_BRANCH + if [[ $? != "0" ]]; then echo "LK_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_ENV; else echo "LK_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi + git ls-remote --heads --exit-code https://github.com/NREL/ssc.git $GIT_BRANCH + if [[ $? != "0" ]]; then echo "SSC_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_ENV; else echo "SSC_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi + + ref=$(git ls-remote --exit-code https://github.com/NREL/lk.git refs/heads/${LK_BRANCH} | awk '{print $1}') echo "ref_of_lk=$ref" | tee --append $GITHUB_ENV + - name: Get cached build data of sibling dependency LK - uses: actions/cache@v2 + uses: actions/cache@v4 id: cachedlk with: - path: ${{ env.GH_WORKSPACE }}/lk - key: ${{ env.RUNS_ON }}-${{ env.ref_of_lk }}-LK + path: lk + key: linux-${{ env.ref_of_lk }}-LK - name: Clone sibling dependency LK if: steps.cachedlk.outputs.cache-hit != 'true' - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: ref: ${{ env.ref_of_lk }} path: lk @@ -59,49 +110,282 @@ jobs: if: steps.cachedlk.outputs.cache-hit != 'true' run: | cd $GITHUB_WORKSPACE/lk - cmake -Bbuild_linux -DCMAKE_BUILD_TYPE=Debug - cmake --build build_linux -- -j - - name: Set LKDIR + cmake -Bbuild_linux -DCMAKE_BUILD_TYPE=Release + cmake --build build_linux -j4 + - name: Set env vars run: | echo "LKDIR=$GITHUB_WORKSPACE/lk" >>$GITHUB_ENV - - name: Set LKD_LIB - run: | - echo "LKD_LIB=$GITHUB_WORKSPACE/lk/build_linux" >>$GITHUB_ENV - - name: Set RAPIDJSONDIR - run: | + echo "LK_LIB=$GITHUB_WORKSPACE/lk/build_linux" >>$GITHUB_ENV echo "RAPIDJSONDIR=$GITHUB_WORKSPACE/ssc" >>$GITHUB_ENV - name: Get git ref of sibling dependency SSC + shell: bash {0} run: | - ref=$(git ls-remote --exit-code git://github.com/NREL/ssc.git refs/heads/develop | awk '{print $1}') + ref=$(git ls-remote --exit-code https://github.com/NREL/ssc.git refs/heads/${SSC_BRANCH} | awk '{print $1}') echo "ref_of_ssc=$ref" | tee --append $GITHUB_ENV - name: Get cached build data of sibling dependency SSC - uses: actions/cache@v2 + uses: actions/cache@v4 id: cachedssc with: - path: ${{ env.GH_WORKSPACE }}/ssc - key: ${{ env.RUNS_ON }}-${{ env.ref_of_ssc }}-SSC + path: ssc + key: windows-${{ env.ref_of_ssc }}-SSC - name: Clone sibling dependency SSC if: steps.cachedssc.outputs.cache-hit != 'true' - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: ref: ${{ env.ref_of_ssc }} path: ssc repository: NREL/ssc + - name: Build WEX + run: | + cd $GITHUB_WORKSPACE/wex + cmake -Bbuild_linux -DCMAKE_BUILD_TYPE=Release + cmake --build build_linux + - name: Save static lib, Dview & wexsandbox + uses: actions/upload-artifact@v4 + with: + name: WEX-linux-x86_64 + path: | + wex/build_linux/tools/DView* + wex/build_linux/tools/wexsandbox* + wex/build_linux/wex*.a + build-on-windows: + runs-on: windows-latest + env: + GITHUB_TOKEN: ${{ secrets.TOKEN_GITHUB }} + steps: + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v2 - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: wex + - name: Set relative paths + shell: bash + run: | + WXMSW3=$GITHUB_WORKSPACE/wx-$WX_VERSION + echo "WXMSW3=$WXMSW3" >> $GITHUB_ENV + - name: Setup cmake + uses: jwlawson/actions-setup-cmake@v2 + with: + cmake-version: '3.24.x' + - name: Get cached build of wxWidgets + uses: actions/cache@v4 + id: cachedwx + with: + path: ${{env.WXMSW3}}/ + key: wxWidgets-${{ env.WX_VERSION }}-windows + - name: Download wxWidgets + if: steps.cachedwx.outputs.cache-hit != 'true' + shell: bash + run: | + curl -L https://github.com/wxWidgets/wxWidgets/releases/download/v$WX_VERSION/wxWidgets-$WX_VERSION.tar.bz2 -o wxWidgets-$WX_VERSION.tar.bz2 + tar jxf wxWidgets-$WX_VERSION.tar.bz2 + - name: Install wxWidgets + if: steps.cachedwx.outputs.cache-hit != 'true' + run: | + cd wxWidgets-$env:WX_VERSION + msbuild build/msw/wx_vc17.sln /t:Build /p:Configuration=Release /p:Platform=x64 + mkdir $env:WXMSW3 + cp -r include $env:WXMSW3 + cp -r lib $env:WXMSW3 + - name: Get branch name for pull request + shell: bash + if: ${{ github.event_name == 'pull_request' }} + run: | + echo "GIT_BRANCH=$GITHUB_BASE_REF" >> $GITHUB_ENV + - name: Get branch name for push + shell: bash + if: ${{ github.event_name == 'push' }} + run: | + echo "GIT_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV + - name: Determine branches for other repos + continue-on-error: true + shell: bash {0} + run: | + git ls-remote --heads --exit-code https://github.com/NREL/lk.git $GIT_BRANCH + if [[ $? != "0" ]]; then echo "LK_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_ENV; else echo "LK_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi + git ls-remote --heads --exit-code https://github.com/NREL/ssc.git $GIT_BRANCH + if [[ $? != "0" ]]; then echo "SSC_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_ENV; else echo "SSC_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi + - name: Get git ref of sibling dependency LK + shell: bash + run: | + ref=$(git ls-remote --exit-code https://github.com/NREL/lk.git refs/heads/$LK_BRANCH | awk '{print $1}') + echo "ref_of_lk=$ref" | tee --append $GITHUB_ENV + - name: Get cached build data of sibling dependency LK + uses: actions/cache@v4 + id: cachedlk + with: + path: lk + key: windows-${{ env.ref_of_lk }}-LK + - name: Checkout lk + if: steps.cachedlk.outputs.cache-hit != 'true' + uses: actions/checkout@v4 + with: + path: lk + repository: NREL/lk + ref: ${{ env.LK_BRANCH }} + - name: Build LK + if: steps.cachedlk.outputs.cache-hit != 'true' + run: | + cd lk + mkdir build + cd build + cmake .. -G "Visual Studio 17 2022" -DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_SYSTEM_VERSION=10 -DSAM_SKIP_TOOLS=1 + MSBuild.exe .\lk.sln /t:Build /p:Configuration=Release + MSBuild.exe .\lk.sln /t:Build /p:Configuration=Debug + - name: Set LK paths + shell: bash + run: | + echo "LKDIR=$GITHUB_WORKSPACE/lk" >>$GITHUB_ENV + echo "LKD_LIB=$GITHUB_WORKSPACE/lk/build/Debug" >>$GITHUB_ENV + echo "LK_LIB=$GITHUB_WORKSPACE/lk/build/Release" >>$GITHUB_ENV + echo "RAPIDJSONDIR=$GITHUB_WORKSPACE/ssc" >>$GITHUB_ENV + - name: Get git ref of sibling dependency SSC + shell: bash + run: | + ref=$(git ls-remote --exit-code https://github.com/NREL/ssc.git refs/heads/patch | awk '{print $1}') + echo "ref_of_ssc=$ref" | tee --append $GITHUB_ENV + - name: Get cached build data of sibling dependency SSC + uses: actions/cache@v4 + id: cachedssc + with: + path: ssc + key: windows-${{ env.ref_of_ssc }}-SSC + - name: Checkout ssc + if: steps.cachedssc.outputs.cache-hit != 'true' + uses: actions/checkout@v4 + with: + path: ssc + repository: NREL/ssc + ref: ${{ env.SSC_BRANCH }} - name: Build WEX run: | - cd $GITHUB_WORKSPACE/wex - cmake -Bbuild_linux -DCMAKE_BUILD_TYPE=Debug - cmake --build build_linux + cd wex + mkdir build + cd build + cmake -G "Visual Studio 17 2022" -DCMAKE_CONFIGURATION_TYPES="Release" -DCMAKE_SYSTEM_VERSION=10 .. + MSBuild.exe .\wex.sln /t:Build /p:Configuration=Release - name: Save static lib, Dview & wexsandbox - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: - name: WEX-${{ env.RUNS_ON }}-x86_64 + name: WEX-windows-x86_64 path: | - ${{ env.GH_WORKSPACE }}/wex/build_linux/tools/DView* - ${{ env.GH_WORKSPACE }}/wex/build_linux/tools/wexsandbox* - ${{ env.GH_WORKSPACE }}/wex/build_linux/wex*.a + wex/build/tools/Release/tools/DView.exe + wex/build/tools/Release/tools/wexsandbox.exe + wex/build/Release/wex.lib + + build-on-mac: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-14-large, macos-latest] + env: + GITHUB_TOKEN: ${{ secrets.TOKEN_GITHUB }} + steps: + - name: Set relative paths + run: | + WXMSW3=$HOME/wx-$WX_VERSION + echo "WXMSW3=$WXMSW3" >> $GITHUB_ENV + - name: Checkout + uses: actions/checkout@v4 + with: + path: wex + - name: Get cached build of wxWidgets + uses: actions/cache@v4 + id: cachedwx + with: + path: ${{env.WXMSW3}}/ + key: wxWidgets-${{ env.WX_VERSION }}-${{ matrix.os }} + - name: Install wxWidgets + if: steps.cachedwx.outputs.cache-hit != 'true' + run: | + curl -L https://github.com/wxWidgets/wxWidgets/releases/download/v$WX_VERSION/wxWidgets-$WX_VERSION.tar.bz2 -o wxWidgets-$WX_VERSION.tar.bz2 + tar jxf wxWidgets-$WX_VERSION.tar.bz2 + cd wxWidgets-$WX_VERSION + ./configure --prefix=$HOME/wx-$WX_VERSION --enable-stl=yes --enable-shared=no --disable-debug_flag --with-cocoa --enable-universal_binary=x86_64,arm64 --enable-unicode --enable-webview --disable-mediactrl --with-cxx=11 --with-macosx-version-min=12 --with-libjpeg=builtin --with-libpng=builtin --with-regex=builtin --with-libtiff=builtin --with-zlib=builtin --with-expat=builtin + make -j3 + make install + sudo ln -s $HOME/wx-$WX_VERSION/bin/wx-config /usr/local/bin/wx-config-3 + wx-config-3 --cflags + echo ${HOME}/wx-$WX_VERSION/bin >> $GITHUB_PATH + - name: Get branch name for pull request + if: ${{ github.event_name == 'pull_request' }} + run: | + echo "GIT_BRANCH=$GITHUB_BASE_REF" >> $GITHUB_ENV + - name: Get branch name for push + if: ${{ github.event_name == 'push' }} + run: | + echo "GIT_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV + - name: Determine branches for other repos + shell: bash {0} + run: | + git ls-remote --heads --exit-code https://github.com/NREL/lk.git $GIT_BRANCH + if [[ $? != "0" ]]; then echo "LK_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_ENV; else echo "LK_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi + git ls-remote --heads --exit-code https://github.com/NREL/ssc.git $GIT_BRANCH + if [[ $? != "0" ]]; then echo "SSC_BRANCH=$DEFAULT_BRANCH" >> $GITHUB_ENV; else echo "SSC_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi + - name: Get git ref of sibling dependency LK + shell: bash {0} + run: | + ref=$(git ls-remote --exit-code https://github.com/NREL/lk.git refs/heads/$LK_BRANCH | awk '{print $1}') + echo "ref_of_lk=$ref" | tee -a $GITHUB_ENV + - name: Get cached build data of sibling dependency LK + uses: actions/cache@v4 + id: cachedlk + with: + path: lk + key: ${{ matrix.os }}-${{ env.ref_of_lk }}-LK + - name: Clone sibling dependency LK + if: steps.cachedlk.outputs.cache-hit != 'true' + uses: actions/checkout@v4 + with: + ref: ${{ env.ref_of_lk }} + path: lk + repository: NREL/lk + - name: Build LK + if: steps.cachedlk.outputs.cache-hit != 'true' + run: | + cd $GITHUB_WORKSPACE/lk + cmake -Bbuild_linux -DCMAKE_BUILD_TYPE=Release + cmake --build build_linux -j4 + - name: Set env vars + run: | + echo "LKDIR=$GITHUB_WORKSPACE/lk" >>$GITHUB_ENV + echo "LK_LIB=$GITHUB_WORKSPACE/lk/build_linux" >>$GITHUB_ENV + echo "RAPIDJSONDIR=$GITHUB_WORKSPACE/ssc" >>$GITHUB_ENV + - name: Get git ref of sibling dependency SSC + shell: bash {0} + run: | + ref=$(git ls-remote --exit-code https://github.com/NREL/ssc.git refs/heads/$SSC_BRANCH | awk '{print $1}') + echo "ref_of_ssc=$ref" | tee -a $GITHUB_ENV + - name: Get cached build data of sibling dependency SSC + uses: actions/cache@v4 + id: cachedssc + with: + path: ssc + key: ${{ matrix.os }}-${{ env.ref_of_ssc }}-SSC + - name: Clone sibling dependency SSC + if: steps.cachedssc.outputs.cache-hit != 'true' + uses: actions/checkout@v4 + with: + ref: ${{ env.ref_of_ssc }} + path: ssc + repository: NREL/ssc + - name: Setup cmake + uses: jwlawson/actions-setup-cmake@v2 + with: + cmake-version: '3.24.x' + - name: Build WEX + run: | + cd wex + cmake -Bbuild_linux -DCMAKE_BUILD_TYPE=Release + cmake --build build_linux + - name: Save static lib, Dview & wexsandbox + uses: actions/upload-artifact@v4 + with: + name: WEX-${{ matrix.os }}-x86_64 + path: | + wex/build_linux/tools/DView* + wex/build_linux/tools/wexsandbox* + wex/build_linux/wex*.a + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 35e126a7..add9b59d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ option(SAM_SKIP_TOOLS "Skips the wex sandbox and Dview builds" OFF) # if (APPLE) - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version") + set(CMAKE_OSX_DEPLOYMENT_TARGET "12" CACHE STRING "Minimum OS X deployment version") endif () if (UNIX AND NOT CMAKE_C_COMPILER) diff --git a/README.md b/README.md index 552fe2d7..e123ddf8 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # WEX: Extensions Library for wxWidgets -[![TravisCI](https://travis-ci.org/NREL/wex.svg?branch=develop)](https://travis-ci.org/NREL/wex) -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FNREL%2Fwex.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FNREL%2Fwex?ref=badge_shield) -WEX is a library of extensions to the [wxWidgets](https://www.wxwidgets.org/) cross-platform user interface (UI) library. These extensions are for custom UI widgets developed for the National Renewable Energy Laboratory's [System Advisor Model (SAM)](https://sam.nrel.gov) and [DView](https://github.com/NREL/wex/wiki/DView) data visualization software. +WEX is a library of extensions to the [wxWidgets](https://www.wxwidgets.org/) cross-platform user interface (UI) library. These extensions are for custom UI widgets developed for the National Renewable Energy Laboratory's [System Advisor Modelâ„¢ (SAMâ„¢)](https://sam.nrel.gov) and [DView](https://github.com/NREL/wex/wiki/DView) data visualization software. WEX also includes two executable programs: diff --git a/include/wex/json_defs.h b/include/wex/json_defs.h deleted file mode 100644 index 4f53efe8..00000000 --- a/include/wex/json_defs.h +++ /dev/null @@ -1,215 +0,0 @@ - -///////////////////////////////////////////////////////////////////////////// -// Name: json_defs.h -// Purpose: shared build defines -// Author: Luciano Cattani -// Created: 2007/10/20 -// RCS-ID: $Id: json_defs.h,v 1.6 2008/03/12 10:48:19 luccat Exp $ -// Copyright: (c) 2007 Luciano Cattani -// Licence: wxWidgets licence -///////////////////////////////////////////////////////////////////////////// - - -#ifndef _WX_JSON_DEFS_H_ -#define _WX_JSON_DEFS_H_ - -// Defines for component version. -// The following symbols should be updated for each new component release -// since some kind of tests, like those of AM_WXCODE_CHECKFOR_COMPONENT_VERSION() -// for "configure" scripts under unix, use them. -#define wxJSON_MAJOR 1 -#define wxJSON_MINOR 2 -#define wxJSON_RELEASE 1 - -// For non-Unix systems (i.e. when building without a configure script), -// users of this component can use the following macro to check if the -// current version is at least major.minor.release -#define wxCHECK_JSON_VERSION(major, minor, release) \ - (wxJSON_MAJOR > (major) || \ - (wxJSON_MAJOR == (major) && wxJSON_MINOR > (minor)) || \ - (wxJSON_MAJOR == (major) && wxJSON_MINOR == (minor) && wxJSON_RELEASE >= (release))) - - -// Defines for shared builds. -// Simple reference for using these macros and for writin components -// which support shared builds: -// -// 1) use the WXDLLIMPEXP_MYCOMP in each class declaration: -// class WXDLLIMPEXP_MYCOMP myCompClass { [...] }; -// -// 2) use the WXDLLIMPEXP_MYCOMP in the declaration of each global function: -// WXDLLIMPEXP_MYCOMP int myGlobalFunc(); -// -// 3) use the WXDLLIMPEXP_DATA_MYCOMP() in the declaration of each global -// variable: -// WXDLLIMPEXP_DATA_MYCOMP(int) myGlobalIntVar; -// -#ifdef WXMAKINGDLL_JSON -#define WXDLLIMPEXP_JSON WXEXPORT -#define WXDLLIMPEXP_DATA_JSON(type) WXEXPORT type -#elif defined(WXUSINGDLL) -#define WXDLLIMPEXP_JSON WXIMPORT -#define WXDLLIMPEXP_DATA_JSON(type) WXIMPORT type -#else // not making nor using DLL -#define WXDLLIMPEXP_JSON -#define WXDLLIMPEXP_DATA_JSON(type) type -#endif - -// the __PRETTY_FUNCTION__ macro expands to the full class's -// member name in the GNU GCC. -// For other compilers we use the standard __wxFUNCTION__ macro -#if !defined( __GNUC__ ) -#define __PRETTY_FUNCTION__ __WXFUNCTION__ -#endif - - - -// define wxJSON_USE_UNICODE if wxWidgets was built with -// unicode support -#if defined( wxJSON_USE_UNICODE ) -#undef wxJSON_USE_UNICODE -#endif -// do not modify the following lines -#if wxUSE_UNICODE == 1 -#define wxJSON_USE_UNICODE -#endif - -// the following macro, if defined, cause the wxJSONValue to store -// pointers to C-strings as pointers to statically allocated -// C-strings. By default this macro is not defined -// #define wxJSON_USE_CSTRING - - -// the following macro, if defined, cause the wxJSONvalue and its -// referenced data structure to store and increment a static -// progressive counter in the ctor. -// this is only usefull for debugging purposes -// #define WXJSON_USE_VALUE_COUNTER - - -// the following macro is used by wxJSON internally and you should not -// modify it. If the platform seems to support 64-bits integers, -// the following lines define the 'wxJSON_64BIT_INT' macro -#if defined( wxLongLong_t ) -#define wxJSON_64BIT_INT -#endif - - -// -// the following macro, if defined, cause the wxJSON library to -// always use 32-bits integers also when the platform seems to -// have native 64-bits support: by default the macro if not defined -// -// #define wxJSON_NO_64BIT_INT -// -#if defined( wxJSON_NO_64BIT_INT ) && defined( wxJSON_64BIT_INT ) -#undef wxJSON_64BIT_INT -#endif - -// -// it seems that some compilers do not define 'long long int' limits -// constants. For example, this is the output of the Borland BCC 5.5 -// compiler when I tried to compile wxJSON with 64-bits integer support: -// Error E2451 ..\src\jsonreader.cpp 1737: Undefined symbol 'LLONG_MAX' -// in function wxJSONReader::Strtoll(const wxString &,__int64 *) -// *** 1 errors in Compile *** -// so, if the constants are not defined, I define them by myself -#if !defined( LLONG_MAX ) -#define LLONG_MAX 9223372036854775807 -#endif - -#if !defined( ULLONG_MAX ) -#define ULLONG_MAX 18446744073709551615 -#endif - -#if !defined( LLONG_MIN ) -#define LLONG_MIN -9223372036854775808 -#endif - - - -// the same applies for all other integer constants -#if !defined( INT_MIN ) -#define INT_MIN -32768 -#endif -#if !defined( INT_MAX ) -#define INT_MAX 32767 -#endif -#if !defined( UINT_MAX ) -#define UINT_MAX 65535 -#endif -#if !defined( LONG_MIN ) -#define LONG_MIN -2147483648 -#endif -#if !defined( LONG_MAX ) -#define LONG_MAX 2147483647 -#endif -#if !defined( ULONG_MAX ) -#define ULONG_MAX 4294967295 -#endif -#if !defined( SHORT_MAX ) -#define SHORT_MAX 32767 -#endif -#if !defined( SHORT_MIN ) -#define SHORT_MIN -32768 -#endif -#if !defined( USHORT_MAX ) -#define USHORT_MAX 65535 -#endif - - - -// -// define the wxJSON_ASSERT() macro to expand to wxASSERT() -// unless the wxJSON_NOABORT_ASSERT is defined -// #define wxJSON_NOABORT_ASSERT -#if defined( wxJSON_NOABORT_ASSERT ) -#define wxJSON_ASSERT( cond ) -#else -#define wxJSON_ASSERT(cond) wxASSERT( cond ); -#endif - - -// -// the following macros are used by the wxJSONWriter::WriteStringValues() -// when the wxJSONWRITER_SPLIT_STRING flag is set -#define wxJSONWRITER_LAST_COL 50 -#define wxJSONWRITER_SPLIT_COL 75 -#define wxJSONWRITER_MIN_LENGTH 15 -#define wxJSONWRITER_TAB_LENGTH 4 - - -// -// some compilers (i.e. MSVC++) defines their own 'snprintf' function -// so if it is not defined, define it in the following lines -// please note that we cannot use the wxWidget's counterpart 'wxSnprintf' -// because the latter uses 'wxChar' but wxJSON only use 'char' -#if !defined(snprintf) && defined(_MSC_VER) -#define snprintf _snprintf -#endif - - -// -// check if wxWidgets is compiled using --enable-stl in which case -// we have to use different aproaches when declaring the array and -// key/value containers (see the docs: wxJSON internals: array and hash_map -#undef wxJSON_USE_STL -//#if defined( wxUSE_STL ) && wxUSE_STL == 1 -//#define wxJSON_USE_STL -//#endif - -// -// defines the MIN and MAX macro for numeric arguments -// note that the safest way to define such functions is using templates -#ifndef MIN -#define MIN(a,b) (a < b ? a : b) -#endif - -#ifndef MAX -#define MAX(a,b) (a > b ? a : b) -#endif - - -#endif // _WX_JSON_DEFS_H_ - - diff --git a/include/wex/jsonreader.h b/include/wex/jsonreader.h deleted file mode 100644 index 86b46271..00000000 --- a/include/wex/jsonreader.h +++ /dev/null @@ -1,166 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: jsonreader.h -// Purpose: the parser of JSON text -// Author: Luciano Cattani -// Created: 2007/09/15 -// RCS-ID: $Id: jsonreader.h,v 1.3 2008/03/03 19:05:45 luccat Exp $ -// Copyright: (c) 2007 Luciano Cattani -// Licence: wxWidgets licence -///////////////////////////////////////////////////////////////////////////// - -#if !defined( _WX_JSONREADER_H ) -#define _WX_JSONREADER_H - -#include -#include -#include - -#include "wex/json_defs.h" -#include "wex/jsonval.h" - -// The flags of the parser -enum { - wxJSONREADER_STRICT = 0, - wxJSONREADER_ALLOW_COMMENTS = 1, - wxJSONREADER_STORE_COMMENTS = 2, - wxJSONREADER_CASE = 4, - wxJSONREADER_MISSING = 8, - wxJSONREADER_MULTISTRING = 16, - wxJSONREADER_COMMENTS_AFTER = 32, - wxJSONREADER_NOUTF8_STREAM = 64, - wxJSONREADER_MEMORYBUFF = 128, - - wxJSONREADER_TOLERANT = wxJSONREADER_ALLOW_COMMENTS | wxJSONREADER_CASE | - wxJSONREADER_MISSING | wxJSONREADER_MULTISTRING, - wxJSONREADER_COMMENTS_BEFORE = wxJSONREADER_ALLOW_COMMENTS | wxJSONREADER_STORE_COMMENTS -}; - -class WXDLLIMPEXP_JSON wxJSONReader { -public: - wxJSONReader(int flags = wxJSONREADER_TOLERANT, int maxErrors = 30); - - virtual ~wxJSONReader(); - - int Parse(const wxString &doc, wxJSONValue *val); - - int Parse(wxInputStream &doc, wxJSONValue *val); - - int GetDepth() const; - - int GetErrorCount() const; - - int GetWarningCount() const; - - const wxArrayString &GetErrors() const; - - const wxArrayString &GetWarnings() const; - - static int UTF8NumBytes(char ch); - - //! skip double quotest in strings - void SetSkipStringDoubleQuotes(bool skip) { m_skip_string_double_quotes = skip; } - - bool GetSkipStringDoubleQuotes() { return m_skip_string_double_quotes; } - -#if defined( wxJSON_64BIT_INT ) - - static bool Strtoll(const wxString &str, wxInt64 *i64); - - static bool Strtoull(const wxString &str, wxUint64 *ui64); - - static bool DoStrto_ll(const wxString &str, wxUint64 *ui64, wxChar *sign); - -#endif - -protected: - - int DoRead(wxInputStream &doc, wxJSONValue &val); - - void AddError(const wxString &descr); - - void AddError(const wxString &fmt, const wxString &str); - - void AddError(const wxString &fmt, wxChar ch); - - void AddWarning(int type, const wxString &descr); - - int GetStart(wxInputStream &is); - - int ReadChar(wxInputStream &is); - - int PeekChar(wxInputStream &is); - - void StoreValue(int ch, const wxString &key, wxJSONValue &value, wxJSONValue &parent); - - int SkipWhiteSpace(wxInputStream &is); - - int SkipComment(wxInputStream &is); - - void StoreComment(const wxJSONValue *parent); - - int ReadString(wxInputStream &is, wxJSONValue &val); - - int ReadToken(wxInputStream &is, int ch, wxString &s); - - int ReadValue(wxInputStream &is, int ch, wxJSONValue &val); - - int ReadUES(wxInputStream &is, char *uesBuffer); - - int AppendUES(wxMemoryBuffer &utf8Buff, const char *uesBuffer); - - int NumBytes(char ch); - - int ConvertCharByChar(wxString &s, const wxMemoryBuffer &utf8Buffer); - - int ReadMemoryBuff(wxInputStream &is, wxJSONValue &val); - - //! Flag that control the parser behaviour, - int m_flags; - - //! Maximum number of errors stored in the error's array - int m_maxErrors; - - //! The current line number (start at 1). - int m_lineNo; - - //! The current column number (start at 1). - int m_colNo; - - //! The current level of object/array annidation (start at ZERO). - int m_level; - - //! The depth level of the read JSON text - int m_depth; - - //! The pointer to the value object that is being read. - wxJSONValue *m_current; - - //! The pointer to the value object that was last stored. - wxJSONValue *m_lastStored; - - //! The pointer to the value object that will be read. - wxJSONValue *m_next; - - //! The comment string read by SkipComment(). - wxString m_comment; - - //! The starting line of the comment string. - int m_commentLine; - - //! The array of error messages. - wxArrayString m_errors; - - //! The array of warning messages. - wxArrayString m_warnings; - - //! The character read by the PeekChar() function (-1 none) - int m_peekChar; - - //! ANSI: do not convert UTF-8 strings - bool m_noUtf8; - - //! skip non-escaped double quotes in strings - bool m_skip_string_double_quotes; -}; - -#endif // not defined _WX_JSONREADER_H diff --git a/include/wex/jsonval.h b/include/wex/jsonval.h deleted file mode 100644 index e66fee55..00000000 --- a/include/wex/jsonval.h +++ /dev/null @@ -1,544 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: jsonval.h -// Purpose: the wxJSONValue class: it holds a JSON value -// Author: Luciano Cattani -// Created: 2007/09/15 -// RCS-ID: $Id: jsonval.h,v 1.4 2008/01/10 21:27:15 luccat Exp $ -// Copyright: (c) 2007 Luciano Cattani -// Licence: wxWidgets licence -///////////////////////////////////////////////////////////////////////////// - -#if !defined( _WX_JSONVAL_H ) -#define _WX_JSONVAL_H - -// for all others, include the necessary headers (this file is usually all you -// need because it includes almost all "standard" wxWidgets headers) -#include -#include -#include -#include - -#include "json_defs.h" - -// forward declarations -class wxJSONReader; - -class wxJSONRefData; - -//! The type of the value held by the wxJSONRefData class -enum wxJSONType { - wxJSONTYPE_INVALID = 0, /*!< the object is not uninitialized */ - wxJSONTYPE_NULL, /*!< the object contains a NULL value */ - wxJSONTYPE_INT, /*!< the object contains an integer */ - wxJSONTYPE_UINT, /*!< the object contains an unsigned integer */ - wxJSONTYPE_DOUBLE, /*!< the object contains a double */ - wxJSONTYPE_STRING, /*!< the object contains a wxString object */ - wxJSONTYPE_CSTRING, /*!< the object contains a static C-string */ - wxJSONTYPE_BOOL, /*!< the object contains a boolean */ - wxJSONTYPE_ARRAY, /*!< the object contains an array of values */ - wxJSONTYPE_OBJECT, /*!< the object contains a map of keys/values */ - wxJSONTYPE_LONG, /*!< the object contains a 32-bit integer */ - wxJSONTYPE_INT64, /*!< the object contains a 64-bit integer */ - wxJSONTYPE_ULONG, /*!< the object contains an unsigned 32-bit integer */ - wxJSONTYPE_UINT64, /*!< the object contains an unsigned 64-bit integer */ - wxJSONTYPE_SHORT, /*!< the object contains a 16-bit integer */ - wxJSONTYPE_USHORT, /*!< the object contains a 16-bit unsigned integer */ - wxJSONTYPE_MEMORYBUFF /*!< the object contains a binary memory buffer */ -}; - -// the comment position: every value only has one comment position -// althrough comments may be splitted into several lines -enum { - wxJSONVALUE_COMMENT_DEFAULT = 0, - wxJSONVALUE_COMMENT_BEFORE, - wxJSONVALUE_COMMENT_AFTER, - wxJSONVALUE_COMMENT_INLINE, -}; - -/*********************************************************************** - - class wxJSONValue - - ***********************************************************************/ - -// class WXDLLIMPEXP_JSON wxJSONValue : public wxObject -class WXDLLIMPEXP_JSON wxJSONValue { - friend class wxJSONReader; - -public: - - // ctors and dtor - wxJSONValue(); - - wxJSONValue(wxJSONType type); - - wxJSONValue(int i); - - wxJSONValue(unsigned int i); - - wxJSONValue(short i); - - wxJSONValue(unsigned short i); - - wxJSONValue(long int i); - - wxJSONValue(unsigned long int i); - -#if defined( wxJSON_64BIT_INT) - - wxJSONValue(wxInt64 i); - - wxJSONValue(wxUint64 ui); - -#endif - - wxJSONValue(bool b); - - wxJSONValue(double d); - - wxJSONValue(const wxChar *str); // assume static ASCIIZ strings - wxJSONValue(const wxString &str); - - wxJSONValue(const wxMemoryBuffer &buff); - - wxJSONValue(const void *buff, size_t len); - - wxJSONValue(const wxJSONValue &other); - - virtual ~wxJSONValue(); - - // functions for retrieving the value type - wxJSONType GetType() const; - - bool IsValid() const; - - bool IsNull() const; - - bool IsInt() const; - - bool IsUInt() const; - - bool IsShort() const; - - bool IsUShort() const; - - bool IsLong() const; - - bool IsULong() const; - -#if defined( wxJSON_64BIT_INT) - - bool IsInt32() const; - - bool IsInt64() const; - - bool IsUInt32() const; - - bool IsUInt64() const; - -#endif - - bool IsBool() const; - - bool IsDouble() const; - - bool IsString() const; - - bool IsCString() const; - - bool IsArray() const; - - bool IsObject() const; - - bool IsMemoryBuff() const; - - // function for retireving the value as ... - int AsInt() const; - - unsigned int AsUInt() const; - - short AsShort() const; - - unsigned short AsUShort() const; - - long int AsLong() const; - - unsigned long AsULong() const; - - bool AsInt(int &i) const; - - bool AsUInt(unsigned int &ui) const; - - bool AsShort(short int &s) const; - - bool AsUShort(unsigned short &us) const; - - bool AsLong(long int &l) const; - - bool AsULong(unsigned long &ul) const; - -#if defined( wxJSON_64BIT_INT) - - wxInt32 AsInt32() const; - - wxUint32 AsUInt32() const; - - wxInt64 AsInt64() const; - - wxUint64 AsUInt64() const; - - bool AsInt32(wxInt32 &i32) const; - - bool AsUInt32(wxUint32 &ui32) const; - - bool AsInt64(wxInt64 &i64) const; - - bool AsUInt64(wxUint64 &ui64) const; - -#endif - - bool AsBool() const; - - double AsDouble() const; - - wxString AsString() const; - - const wxChar *AsCString() const; - - bool AsBool(bool &b) const; - - bool AsDouble(double &d) const; - - bool AsString(wxString &str) const; - - bool AsCString(wxChar *ch) const; - - wxMemoryBuffer AsMemoryBuff() const; - - bool AsMemoryBuff(wxMemoryBuffer &buff) const; - - // get members names, size and other info - bool HasMember(unsigned index) const; - - bool HasMember(const wxString &key) const; - - int Size() const; - - wxArrayString GetMemberNames() const; - - // appending items, resizing and deleting items - wxJSONValue &Append(const wxJSONValue &value); - - wxJSONValue &Append(bool b); - - wxJSONValue &Append(int i); - - wxJSONValue &Append(unsigned int ui); - - wxJSONValue &Append(short int i); - - wxJSONValue &Append(unsigned short int ui); - - wxJSONValue &Append(long int l); - - wxJSONValue &Append(unsigned long int ul); - -#if defined( wxJSON_64BIT_INT ) - - wxJSONValue &Append(wxInt64 i); - - wxJSONValue &Append(wxUint64 ui); - -#endif - - wxJSONValue &Append(double d); - - wxJSONValue &Append(const wxChar *str); - - wxJSONValue &Append(const wxString &str); - - wxJSONValue &Append(const wxMemoryBuffer &buff); - - wxJSONValue &Append(const void *buff, size_t len); - - bool Remove(int index); - - bool Remove(const wxString &key); - - void Clear(); - - bool Cat(const wxChar *str); - - bool Cat(const wxString &str); - - bool Cat(const wxMemoryBuffer &buff); - - // retrieve an item - wxJSONValue &Item(unsigned index); - - wxJSONValue &Item(const wxString &key); - - wxJSONValue ItemAt(unsigned index) const; - - wxJSONValue ItemAt(const wxString &key) const; - - wxJSONValue &operator[](unsigned index); - - wxJSONValue &operator[](const wxString &key); - - wxJSONValue &operator=(int i); - - wxJSONValue &operator=(unsigned int ui); - - wxJSONValue &operator=(short int i); - - wxJSONValue &operator=(unsigned short int ui); - - wxJSONValue &operator=(long int l); - - wxJSONValue &operator=(unsigned long int ul); - -#if defined( wxJSON_64BIT_INT ) - - wxJSONValue &operator=(wxInt64 i); - - wxJSONValue &operator=(wxUint64 ui); - -#endif - - wxJSONValue &operator=(bool b); - - wxJSONValue &operator=(double d); - - wxJSONValue &operator=(const wxChar *str); - - wxJSONValue &operator=(const wxString &str); - - wxJSONValue &operator=(const wxMemoryBuffer &buff); - - // wxJSONValue& operator = ( const void* buff, size_t len ); cannot be declared - wxJSONValue &operator=(const wxJSONValue &value); - - // get the value or a default value - wxJSONValue Get(const wxString &key, const wxJSONValue &defaultValue) const; - - // comparison function - bool IsSameAs(const wxJSONValue &other) const; - - // comment-related functions - int AddComment(const wxString &str, int position = wxJSONVALUE_COMMENT_DEFAULT); - - int AddComment(const wxArrayString &comments, int position = wxJSONVALUE_COMMENT_DEFAULT); - - wxString GetComment(int idx = -1) const; - - int GetCommentPos() const; - - int GetCommentCount() const; - - void ClearComments(); - - const wxArrayString &GetCommentArray() const; - - // debugging functions - wxString GetInfo() const; - - wxString Dump(bool deep = false, int mode = 0) const; - - //misc functions - wxJSONRefData *GetRefData() const; - - wxJSONRefData *SetType(wxJSONType type); - - int GetLineNo() const; - - void SetLineNo(int num); - - // public static functions: mainly used for debugging - static wxString TypeToString(wxJSONType type); - - static wxString MemoryBuffToString(const wxMemoryBuffer &buff, size_t len = -1); - - static wxString MemoryBuffToString(const void *buff, size_t len, size_t actualLen = -1); - - static int CompareMemoryBuff(const wxMemoryBuffer &buff1, const wxMemoryBuffer &buff2); - - static int CompareMemoryBuff(const wxMemoryBuffer &buff1, const void *buff2); - - static wxMemoryBuffer ArrayToMemoryBuff(const wxJSONValue &value); - -protected: - wxJSONValue *Find(unsigned index) const; - - wxJSONValue *Find(const wxString &key) const; - - void DeepCopy(const wxJSONValue &other); - - wxJSONRefData *Init(wxJSONType type); - - wxJSONRefData *COW(); - - // overidden from wxObject - virtual wxJSONRefData *CloneRefData(const wxJSONRefData *data) const; - - virtual wxJSONRefData *CreateRefData() const; - - void SetRefData(wxJSONRefData *data); - - void Ref(const wxJSONValue &clone); - - void UnRef(); - - void UnShare(); - - void AllocExclusive(); - - //! the referenced data - wxJSONRefData *m_refData; - - // used for debugging purposes: only in debug builds. -#if defined( WXJSON_USE_VALUE_COUNTER ) - int m_progr; - static int sm_progr; -#endif -}; - -WX_DECLARE_OBJARRAY(wxJSONValue, wxJSONInternalArray); - -WX_DECLARE_STRING_HASH_MAP(wxJSONValue, wxJSONInternalMap); - -/*********************************************************************** - - class wxJSONRefData - - ***********************************************************************/ - -//! The actual value held by the wxJSONValue class (internal use) -/*! - Note that this structure is a \b union as in versions prior to 0.4.x - The union just stores primitive types and not complex types which are - stored in separate data members of the wxJSONRefData structure. - - This organization give us more flexibility when retrieving compatible - types such as ints unsigned ints, long and so on. - To know more about the internal structure of the wxJSONValue class - see \ref pg_json_internals. - */ -union wxJSONValueHolder { - int m_valInt; - unsigned int m_valUInt; - short int m_valShort; - unsigned short m_valUShort; - long int m_valLong; - unsigned long m_valULong; - double m_valDouble; - const wxChar *m_valCString; - bool m_valBool; -#if defined( wxJSON_64BIT_INT ) - wxInt64 m_valInt64; - wxUint64 m_valUInt64; -#endif -}; - -// -// access to the (unsigned) integer value is done through -// the VAL_INT macro which expands to the 'long' integer -// data member of the 'long long' integer if 64-bits integer -// support is enabled -#if defined( wxJSON_64BIT_INT ) -#define VAL_INT m_valInt64 -#define VAL_UINT m_valUInt64 -#else -#define VAL_INT m_valLong -#define VAL_UINT m_valULong -#endif - -double json_double(const wxJSONValue &jv, double defaultval = 0.0, bool *Exists = NULL); - -int json_integer(const wxJSONValue &jv, int defaultval = 0, bool *Exists = NULL); - -wxString json_string(const wxJSONValue &jv, const wxString &defaultval = wxEmptyString, bool *Exists = NULL); - -// class WXDLLIMPEXP_JSON wxJSONRefData : public wxObjectRefData -class WXDLLIMPEXP_JSON wxJSONRefData { - // friend class wxJSONReader; - friend class wxJSONValue; - - friend class wxJSONWriter; - -public: - - wxJSONRefData(); - - virtual ~wxJSONRefData(); - - int GetRefCount() const; - - // there is no need to define copy ctor - - //! the references count - int m_refCount; - - //! The actual type of the value held by this object. - wxJSONType m_type; - - //! The JSON value held by this object. - /*! - This data member contains the JSON data types defined by the - JSON syntax with the exception of the complex objects. - This data member is an union of the primitive types - so that it is simplier to cast them in other compatible types. - */ - wxJSONValueHolder m_value; - - //! The JSON string value. - wxString m_valString; - - //! The JSON array value. - wxJSONInternalArray m_valArray; - - //! The JSON object value. - wxJSONInternalMap m_valMap; - - //! The position of the comment line(s), if any. - /*! - The data member contains one of the following constants: - \li \c wxJSONVALUE_COMMENT_BEFORE - \li \c wxJSONVALUE_COMMENT_AFTER - \li \c wxJSONVALUE_COMMENT_INLINE - */ - int m_commentPos; - - //! The array of comment lines; may be empty. - wxArrayString m_comments; - - //! The line number when this value was read - /*! - This data member is used by the wxJSONReader class and it is - used to store the line number of the JSON text document where - the value appeared. This value is compared to the line number - of a comment line in order to obtain the value which a - comment refersto. - */ - int m_lineNo; - - //! The pointer to the memory buffer object - /*! - Note that despite using reference counting, the \b wxMemoryBuffer is not a - \e copy-on-write structure so the wxJSON library uses some tricks in order to - avoid the side effects of copying / assigning wxMemoryBuffer objects - */ - wxMemoryBuffer *m_memBuff; - - // used for debugging purposes: only in debug builds. -#if defined( WXJSON_USE_VALUE_COUNTER ) - int m_progr; - static int sm_progr; -#endif -}; - -const wxJSONInternalArray *wxJSONValueAsArray(const wxJSONValue &val); - -const wxJSONInternalMap *wxJSONValueAsMap(const wxJSONValue &val); - -#endif // not defined _WX_JSONVAL_H diff --git a/include/wex/jsonwriter.h b/include/wex/jsonwriter.h deleted file mode 100644 index 87976e45..00000000 --- a/include/wex/jsonwriter.h +++ /dev/null @@ -1,115 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: jsonwriter.h -// Purpose: the generator of JSON text from a JSON value -// Author: Luciano Cattani -// Created: 2007/09/15 -// RCS-ID: $Id: jsonwriter.h,v 1.4 2008/03/03 19:05:45 luccat Exp $ -// Copyright: (c) 2007 Luciano Cattani -// Licence: wxWidgets licence -///////////////////////////////////////////////////////////////////////////// - -#if !defined( _WX_JSONWRITER_H ) -#define _WX_JSONWRITER_H - -#include -#include - -#include "wex/json_defs.h" -#include "wex/jsonval.h" - -enum { - wxJSONWRITER_NONE = 0, - wxJSONWRITER_STYLED = 1, - wxJSONWRITER_WRITE_COMMENTS = 2, - wxJSONWRITER_COMMENTS_BEFORE = 4, - wxJSONWRITER_COMMENTS_AFTER = 8, - wxJSONWRITER_SPLIT_STRING = 16, - wxJSONWRITER_NO_LINEFEEDS = 32, - wxJSONWRITER_ESCAPE_SOLIDUS = 64, - wxJSONWRITER_MULTILINE_STRING = 128, - wxJSONWRITER_RECOGNIZE_UNSIGNED = 256, - wxJSONWRITER_TAB_INDENT = 512, - wxJSONWRITER_NO_INDENTATION = 1024, - wxJSONWRITER_NOUTF8_STREAM = 2048, - wxJSONWRITER_MEMORYBUFF = 4096 -}; - -// class declaration - -class WXDLLIMPEXP_JSON wxJSONWriter { -public: - wxJSONWriter(int style = wxJSONWRITER_STYLED, int indent = 0, int step = 3); - - ~wxJSONWriter(); - - void Write(const wxJSONValue &value, wxString &str); - - void Write(const wxJSONValue &value, wxOutputStream &os); - - void SetDoubleFmtString(const char *fmt); - -protected: - - int DoWrite(wxOutputStream &os, const wxJSONValue &value, const wxString *key, bool comma); - - int WriteIndent(wxOutputStream &os); - - int WriteIndent(wxOutputStream &os, int num); - - bool IsSpace(wxChar ch); - - bool IsPunctuation(wxChar ch); - - int WriteString(wxOutputStream &os, const wxString &str); - - int WriteStringValue(wxOutputStream &os, const wxString &str); - - int WriteNullValue(wxOutputStream &os); - - int WriteIntValue(wxOutputStream &os, const wxJSONValue &v); - - int WriteUIntValue(wxOutputStream &os, const wxJSONValue &v); - - int WriteBoolValue(wxOutputStream &os, const wxJSONValue &v); - - int WriteDoubleValue(wxOutputStream &os, const wxJSONValue &v); - - int WriteMemoryBuff(wxOutputStream &os, const wxMemoryBuffer &buff); - - int WriteInvalid(wxOutputStream &os); - - int WriteSeparator(wxOutputStream &os); - - int WriteKey(wxOutputStream &os, const wxString &key); - - int WriteComment(wxOutputStream &os, const wxJSONValue &value, bool indent); - - int WriteError(const wxString &err); - -private: - //! The style flag is a combination of wxJSONWRITER_(something) constants. - int m_style; - - //! The initial indentation value, in number of spaces. - int m_indent; - - //! The indentation increment, in number of spaces. - int m_step; - - //! JSON value objects can be nested; this is the level of annidation (used internally). - int m_level; - - // The line number when printing JSON text output (not yet used) - int m_lineNo; - - // The column number when printing JSON text output - int m_colNo; - - // Flag used in ANSI mode that controls UTF-8 conversion - bool m_noUtf8; - - // The format string for printing doubles - char *m_fmt; -}; - -#endif // not defined _WX_JSONWRITER_H diff --git a/include/wex/plot/plcolourmap.h b/include/wex/plot/plcolourmap.h index 19c6208e..577ab463 100644 --- a/include/wex/plot/plcolourmap.h +++ b/include/wex/plot/plcolourmap.h @@ -41,6 +41,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "wex/plot/plplot.h" +#define wxCONTOUR_BG wxStockGDI::GetColour(wxStockGDI::COLOUR_LIGHTGREY) + class wxPLColourMap : public wxPLSideWidgetBase { public: wxPLColourMap(double min = 0, double max = 1); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e0d4d817..b53f3afa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,9 +33,6 @@ set(WEX_SRC exttextstream.cpp exttree.cpp gleasy.cpp - jsonreader.cpp - jsonval.cpp - jsonwriter.cpp label.cpp lkscript.cpp metro.cpp diff --git a/src/clipper/clipper.cpp b/src/clipper/clipper.cpp index 741aa97c..34e73095 100644 --- a/src/clipper/clipper.cpp +++ b/src/clipper/clipper.cpp @@ -1796,7 +1796,7 @@ namespace ClipperLib { else if (e1->PolyTyp != e2->PolyTyp) { //toggle subj open path OutIdx on/off when Abs(clip.WndCnt) == 1 ... - if ((e1->WindDelta == 0) && abs(e2->WindCnt) == 1 && + if ((e1->WindDelta == 0) && std::abs(e2->WindCnt) == 1 && (m_ClipType != ctUnion || e2->WindCnt2 == 0)) { AddOutPt(e1, Pt); diff --git a/src/easycurl.cpp b/src/easycurl.cpp index bda3c28b..ee1d005a 100644 --- a/src/easycurl.cpp +++ b/src/easycurl.cpp @@ -50,7 +50,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #include -#include #include #include #include diff --git a/src/jsonreader.cpp b/src/jsonreader.cpp deleted file mode 100644 index 12ff0e72..00000000 --- a/src/jsonreader.cpp +++ /dev/null @@ -1,2048 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: jsonreader.cpp -// Purpose: the wxJSONReader class: a JSON text parser -// Author: Luciano Cattani -// Created: 2007/10/14 -// RCS-ID: $Id: jsonreader.cpp,v 1.12 2008/03/12 10:48:19 luccat Exp $ -// Copyright: (c) 2007 Luciano Cattani -// Licence: wxWidgets licence -///////////////////////////////////////////////////////////////////////////// - -#include "wex/jsonreader.h" - -#include -#include -#include -#include - -/*! \class wxJSONReader - \brief The JSON parser - - The class is a JSON parser which reads a JSON formatted text and stores - values in the \c wxJSONValue structure. - The ctor accepts two parameters: the \e style flag, which controls how - much error-tolerant should the parser be and an integer which is - the maximum number of errors and warnings that have to be reported - (the default is 30). - - If the JSON text document does not contain an open/close JSON character the - function returns an \b invalid value object; in other words, the - wxJSONValue::IsValid() function returns FALSE. - This is the case of a document that is empty or contains only - whitespaces or comments. - If the document contains a starting object/array character immediatly - followed by a closing object/array character - (i.e.: \c {} ) then the function returns an \b empty array or object - JSON value. - This is a valid JSON object of type wxJSONTYPE_OBJECT or wxJSONTYPE_ARRAY - whose wxJSONValue::Size() function returns ZERO. - - \par JSON text - - The wxJSON parser just skips all characters read from the - input JSON text until the start-object '{' or start-array '[' characters - are encontered (see the GetStart() function). - This means that the JSON input text may contain anything - before the first start-object/array character except these two chars themselves - unless they are included in a C/C++ comment. - Comment lines that apear before the first start array/object character, - are non ignored if the parser is constructed with the wxJSONREADER_STORE_COMMENT - flag: they are added to the comment's array of the root JSON value. - - Note that the parsing process stops when the internal DoRead() function - returns. Because that function is recursive, the top-level close-object - '}' or close-array ']' character cause the top-level DoRead() function - to return thus stopping the parsing process regardless the EOF condition. - This means that the JSON input text may contain anything \b after - the top-level close-object/array character. - Here are some examples: - - Returns a wxJSONTYPE_INVALID value (invalid JSON value) - \code - // this text does not contain an open array/object character - \endcode - - Returns a wxJSONTYPE_OBJECT value of Size() = 0 - \code - { - } - \endcode - - Returns a wxJSONTYPE_ARRAY value of Size() = 0 - \code - [ - ] - \endcode - - Text before and after the top-level open/close characters is ignored. - \code - This non-JSON text does not cause the parser to report errors or warnings - { - } - This non-JSON text does not cause the parser to report errors or warnings - \endcode - - \par Extensions - - The wxJSON parser recognizes all JSON text plus some extensions - that are not part of the JSON syntax but that many other JSON - implementations do recognize. - If the input text contains the following non-JSON text, the parser - reports the situation as \e warnings and not as \e errors unless - the parser object was constructed with the wxJSONREADER_STRICT - flag. In the latter case the wxJSON parser is not tolerant. - - \li C/C++ comments: the parser recognizes C and C++ comments. - Comments can optionally be stored in the value they refer - to and can also be written back to the JSON text document. - To know more about comment storage see \ref wxjson_comments - - \li case tolerance: JSON syntax states that the literals \c null, - \c true and \c false must be lowercase; the wxJSON parser - also recognizes mixed case literals such as, for example, - \b Null or \b FaLSe. A \e warning is emitted. - - \li wrong or missing closing character: wxJSON parser is tolerant - about the object / array closing character. When an open-array - character '[' is encontered, the parser expects the - corresponding close-array character ']'. If the character - encontered is a close-object char '}' a warning is reported. - A warning is also reported if the character is missing when - the end-of-file is reached. - - \li multi-line strings: this feature allows a JSON string type to be - splitted in two or more lines as in the standard C/C++ - languages. The drawback is that this feature is error-prone - and you have to use it with care. - For more info about this topic read \ref wxjson_tutorial_style_split - - Note that you can control how much error-tolerant should the parser be - and also you can specify how many and what extensions are recognized. - See the constructor's parameters for more details. - - \par Unicode vs ANSI - - The parser can read JSON text from two very different kind of objects: - - \li a string object (\b wxString) - \li a stream object (\b wxInputStream) - - When the input is from a string object, the character represented in the - string is platform- and mode- dependant; in other words, characters are - represented differently: in ANSI builds they depend on the charset in use - and in Unicode builds they depend on the platform (UCS-2 on win32, UCS-4 - or UTF-8 on GNU/Linux). - - When the input is from a stream object, the only recognized encoding format - is UTF-8 for both ANSI and Unicode builds. - - \par Example: - - \code - wxJSONValue value; - wxJSONReader reader; - - // open a text file that contains the UTF-8 encoded JSON text - wxFFileInputStream jsonText( _T("filename.utf8"), _T("r")); - - // read the file - int numErrors = reader.Parse( jsonText, &value ); - - if ( numErrors > 0 ) { - ::MessageBox( _T("Error reading the input file")); - } - \endcode - - Starting from version 1.1.0 the wxJSON reader and the writer has changed in - their internal organization. - To know more about ANSI and Unicode mode read \ref wxjson_tutorial_unicode. - */ - -// if you have the debug build of wxWidgets and wxJSON you can see -// trace messages by setting the: -// WXTRACE=traceReader StoreComment -// environment variable -#if wxUSE_LOG_TRACE -static const wxChar* traceMask = _T("traceReader"); -static const wxChar* storeTraceMask = _T("StoreComment"); -#endif - -//! Ctor -/*! - Construct a JSON parser object with the given parameters. - - JSON parser objects should always be constructed on the stack but - it does not hurt to have a global JSON parser. - - \param flags this paramter controls how much error-tolerant should the - parser be - - \param maxErrors the maximum number of errors (and warnings, too) that are - reported by the parser. When the number of errors reaches this limit, - the parser stops to read the JSON input text and no other error is - reported. - - The \c flag parameter is the combination of ZERO or more of the - following constants OR'ed toghether: - - \li wxJSONREADER_ALLOW_COMMENTS: C/C++ comments are recognized by the - parser; a warning is reported by the parser - \li wxJSONREADER_STORE_COMMENTS: C/C++ comments, if recognized, are - stored in the value they refer to and can be rewritten back to - the JSON text - \li wxJSONREADER_CASE: the parser recognizes mixed-case literal strings - \li wxJSONREADER_MISSING: the parser allows missing or wrong close-object - and close-array characters - \li wxJSONREADER_MULTISTRING: strings may be splitted in two or more - lines - \li wxJSONREADER_COMMENTS_AFTER: if STORE_COMMENTS if defined, the parser - assumes that comment lines apear \b before the value they - refer to unless this constant is specified. In the latter case, - comments apear \b after the value they refer to. - \li wxJSONREADER_NOUTF8_STREAM: suppress UTF-8 conversion when reading a - string value from a stream: the reader assumes that the input stream - is encoded in ANSI format and not in UTF-8; only meaningfull in ANSI - builds, this flag is simply ignored in Unicode builds. - - You can also use the following shortcuts to specify some predefined - flag's combinations: - - \li wxJSONREADER_STRICT: all wxJSON extensions are reported as errors, this - is the same as specifying a ZERO value as \c flags. - \li wxJSONREADER_TOLERANT: this is the same as ALLOW_COMMENTS | CASE | - MISSING | MULTISTRING; all wxJSON extensions are turned on but comments - are not stored in the value objects. - - \par Example: - - The following code fragment construct a JSON parser, turns on all - wxJSON extensions and also stores C/C++ comments in the value object - they refer to. The parser assumes that the comments apear before the - value: - - \code - wxJSONReader reader( wxJSONREADER_TOLERANT | wxJSONREADER_STORE_COMMENTS ); - wxJSONValue root; - int numErrors = reader.Parse( jsonText, &root ); - \endcode - */ -wxJSONReader::wxJSONReader(int flags, int maxErrors) { - m_flags = flags; - m_maxErrors = maxErrors; - m_noUtf8 = false; - - m_skip_string_double_quotes = false; // normal behavior JSON strings start with " and end with " - -#if !defined( wxJSON_USE_UNICODE ) - // in ANSI builds we can suppress UTF-8 conversion for both the writer and the reader - if ( m_flags & wxJSONREADER_NOUTF8_STREAM ) { - m_noUtf8 = true; - } -#endif -} - -//! Dtor - does nothing -wxJSONReader::~wxJSONReader() { -} - -//! Parse the JSON document. -/*! - The two overloaded versions of the \c Parse() function read a - JSON text stored in a wxString object or in a wxInputStream - object. - - If \c val is a NULL pointer, the function does not store the - values: it can be used as a JSON checker in order to check the - syntax of the document. - Returns the number of \b errors found in the document. - If the returned value is ZERO and the parser was constructed - with the \c wxJSONREADER_STRICT flag, then the parsed document - is \e well-formed and it only contains valid JSON text. - - If the \c wxJSONREADER_TOLERANT flag was used in the parser's - constructor, then a return value of ZERO - does not mean that the document is \e well-formed because it may - contain comments and other extensions that are not fatal for the - wxJSON parser but other parsers may fail to recognize. - You can use the \c GetWarningCount() function to know how many - wxJSON extensions are present in the JSON input text. - - Note that the JSON value object \c val is not cleared by this - function unless its type is of the wrong type. - In other words, if \c val is of type wxJSONTYPE_ARRAY and it already - contains 10 elements and the input document starts with a - '[' (open-array char) then the elements read from the document are - \b appended to the existing ones. - - On the other hand, if the text document starts with a '{' (open-object) char - then this function must change the type of the \c val object to - \c wxJSONTYPE_OBJECT and the old content of 10 array elements will be lost. - - \par Different input types - - The real parsing process in done using UTF-8 streams. If the input is - from a \b wxString object, the Parse function first converts the input string - in a temporary \b wxMemoryInputStream which contains the UTF-8 conversion - of the string itself. - Next, the overloaded Parse function is called. - - @param doc the JSON text that has to be parsed - @param val the wxJSONValue object that contains the parsed text; if NULL the - parser do not store anything but errors and warnings are reported - @return the total number of errors encontered - */ -int -wxJSONReader::Parse(const wxString &doc, wxJSONValue *val) { -#if !defined( wxJSON_USE_UNICODE ) - // in ANSI builds input from a string never use UTF-8 conversion - bool noUtf8_bak = m_noUtf8; // save the current setting - m_noUtf8 = true; -#endif - - // convert the string to a UTF-8 / ANSI memory stream and calls overloaded Parse() - char *readBuff = 0; - wxCharBuffer utf8CB = doc.ToUTF8(); // the UTF-8 buffer -#if !defined( wxJSON_USE_UNICODE ) - wxCharBuffer ansiCB( doc.c_str()); // the ANSI buffer - if ( m_noUtf8 ) { - readBuff = ansiCB.data(); - } - else { - readBuff = utf8CB.data(); - } -#else - readBuff = utf8CB.data(); -#endif - - // now construct the temporary memory input stream - size_t len = strlen(readBuff); - wxMemoryInputStream is(readBuff, len); - - int numErr = Parse(is, val); -#if !defined( wxJSON_USE_UNICODE ) - m_noUtf8 = noUtf8_bak; -#endif - return numErr; -} - -//! \overload Parse( const wxString&, wxJSONValue* ) -int -wxJSONReader::Parse(wxInputStream &is, wxJSONValue *val) { - // if val == 0 the 'temp' JSON value will be passed to DoRead() - wxJSONValue temp; - m_level = 0; - m_depth = 0; - m_lineNo = 1; - m_colNo = 1; - m_peekChar = -1; - m_errors.clear(); - m_warnings.clear(); - - // if a wxJSONValue is not passed to the Parse function - // we set the temparary object created on the stack - // I know this will slow down the validation of input - if (val == 0) { - val = &temp; - } - wxASSERT(val); - - // set the wxJSONValue object's pointers for comment storage - m_next = val; - m_next->SetLineNo(-1); - m_lastStored = 0; - m_current = 0; - - int ch = GetStart(is); - switch (ch) { - case '{': - val->SetType(wxJSONTYPE_OBJECT); - break; - case '[': - val->SetType(wxJSONTYPE_ARRAY); - break; - default: - AddError(_T("Cannot find a start object/array character")); - return m_errors.size(); - break; - } - - // returning from DoRead() could be for EOF or for - // the closing array-object character - // if -1 is returned, it is as an error because the lack - // of close-object/array characters - // note that the missing close-chars error messages are - // added by the DoRead() function - ch = DoRead(is, *val); - return m_errors.size(); -} - -//! Returns the start of the document -/*! - This is the first function called by the Parse() function and it searches - the input stream for the starting character of a JSON text and returns it. - JSON text start with '{' or '['. - If the two starting characters are inside a C/C++ comment, they - are ignored. - Returns the JSON-text start character or -1 on EOF. - - @param is the input stream that contains the JSON text - @return -1 on errors or EOF; one of '{' or '[' - */ -int -wxJSONReader::GetStart(wxInputStream &is) { - int ch = 0; - do { - switch (ch) { - case 0: - ch = ReadChar(is); - break; - case '{': - return ch; - break; - case '[': - return ch; - break; - case '/': - ch = SkipComment(is); - StoreComment(0); - break; - default: - ch = ReadChar(is); - break; - } - } while (ch >= 0); - return ch; -} - -//! Return a reference to the error message's array. -const wxArrayString & -wxJSONReader::GetErrors() const { - return m_errors; -} - -//! Return a reference to the warning message's array. -const wxArrayString & -wxJSONReader::GetWarnings() const { - return m_warnings; -} - -//! Return the depth of the JSON input text -/*! - The function returns the number of times the recursive \c DoRead function was - called in the parsing process thus returning the maximum depth of the JSON - input text. - */ -int -wxJSONReader::GetDepth() const { - return m_depth; -} - -//! Return the size of the error message's array. -int -wxJSONReader::GetErrorCount() const { - return m_errors.size(); -} - -//! Return the size of the warning message's array. -int -wxJSONReader::GetWarningCount() const { - return m_warnings.size(); -} - -//! Read a character from the input JSON document. -/*! - The function returns the next byte from the UTF-8 stream as an INT. - In case of errors or EOF, the function returns -1. - The function also updates the \c m_lineNo and \c m_colNo data - members and converts all CR+LF sequence in LF. - - This function only returns one byte UTF-8 (one code unit) - at a time and not Unicode code points. - The only reason for this function is to process line and column - numbers. - - @param is the input stream that contains the JSON text - @return the next char (one single byte) in the input stream or -1 on error or EOF - */ -int -wxJSONReader::ReadChar(wxInputStream &is) { - if (is.Eof()) { - return -1; - } - - unsigned char ch = is.GetC(); - size_t last = is.LastRead(); // returns ZERO if EOF - if (last == 0) { - return -1; - } - - // the function also converts CR in LF. only LF is returned - // in the case of CR+LF - int nextChar; - - if (ch == '\r') { - m_colNo = 1; - nextChar = PeekChar(is); - if (nextChar == -1) { - return -1; - } else if (nextChar == '\n') { - ch = is.GetC(); - } - } - if (ch == '\n') { - ++m_lineNo; - m_colNo = 1; - } else { - ++m_colNo; - } - return (int) ch; -} - -//! Peek a character from the input JSON document -/*! - This function just calls the \b Peek() function on the stream - and returns it. - - @param is the input stream that contains the JSON text - @return the next char (one single byte) in the input stream or -1 on error or EOF - */ -int -wxJSONReader::PeekChar(wxInputStream &is) { - int ch = -1; - unsigned char c; - if (!is.Eof()) { - c = is.Peek(); - ch = c; - } - return ch; -} - -//! Reads the JSON text document (internal use) -/*! - This is a recursive function that is called by \c Parse() - and by the \c DoRead() function itself when a new object / - array character is encontered. - The function returns when a EOF condition is encontered or - when the corresponding close-object / close-array char is encontered. - The function also increments the \c m_level - data member when it is entered and decrements it on return. - It also sets \c m_depth equal to \c m_level if \c m_depth is - less than \c m_level. - - The function is the heart of the wxJSON parser class but it is - also very easy to understand because JSON syntax is very - easy. - - Returns the last close-object/array character read or -1 on EOF. - - @param is the input stream that contains the JSON text - @param parent the JSON value object that is the parent of all subobjects - read by the function until the next close-object/array (for - the top-level \c DoRead function \c parent is the root JSON object) - @return one of close-array or close-object char or -1 on error or EOF - */ -int -wxJSONReader::DoRead(wxInputStream &is, wxJSONValue &parent) { - ++m_level; - if (m_depth < m_level) { - m_depth = m_level; - } - - // 'value' is the wxJSONValue structure that has to be - // read. Data read from the JSON text input is stored - // in the following object. - wxJSONValue value(wxJSONTYPE_INVALID); - - // sets the pointers to the current, next and last-stored objects - // in order to determine the value to which a comment refers to - m_next = &value; - m_current = &parent; - m_current->SetLineNo(m_lineNo); - m_lastStored = 0; - - // the 'key' string is stored from 'value' when a ':' is encontered - wxString key; - - // the character read: -1=EOF, 0=to be read - int ch = 0; - - do { // we read until ch < 0 - switch (ch) { - case 0: - ch = ReadChar(is); - break; - case ' ': - case '\t': - case '\n': - case '\r': - ch = SkipWhiteSpace(is); - break; - case -1: // the EOF - break; - case '/': - ch = SkipComment(is); - StoreComment(&parent); - break; - - case '{': - if (parent.IsObject()) { - if (key.empty()) { - AddError(_T("\'{\' is not allowed here (\'name\' is missing")); - } - if (value.IsValid()) { - AddError(_T("\'{\' cannot follow a \'value\'")); - } - } else if (parent.IsArray()) { - if (value.IsValid()) { - AddError(_T("\'{\' cannot follow a \'value\' in JSON array")); - } - } else { wxJSON_ASSERT(0); // always fails - } - - // the openobject char cause the DoRead() to be called recursively - value.SetType(wxJSONTYPE_OBJECT); - ch = DoRead(is, value); - break; - - case '}': - if (!parent.IsObject()) { - AddWarning(wxJSONREADER_MISSING, - _T("Trying to close an array using the \'}\' (close-object) char")); - } - // close-object: store the current value, if any - StoreValue(ch, key, value, parent); - m_current = &parent; - m_next = 0; - m_current->SetLineNo(m_lineNo); - ch = ReadChar(is); - return ch; - break; - - case '[': - if (parent.IsObject()) { - if (key.empty()) { - AddError(_T("\'[\' is not allowed here (\'name\' is missing")); - } - if (value.IsValid()) { - AddError(_T("\'[\' cannot follow a \'value\' text")); - } - } else if (parent.IsArray()) { - if (value.IsValid()) { - AddError(_T("\'[\' cannot follow a \'value\'")); - } - } else { wxJSON_ASSERT(0); // always fails - } - // open-array cause the DoRead() to be called recursively - value.SetType(wxJSONTYPE_ARRAY); - ch = DoRead(is, value); - break; - - case ']': - if (!parent.IsArray()) { - // wrong close-array char (should be close-object) - AddWarning(wxJSONREADER_MISSING, - _T("Trying to close an object using the \']\' (close-array) char")); - } - StoreValue(ch, key, value, parent); - m_current = &parent; - m_next = 0; - m_current->SetLineNo(m_lineNo); - return 0; // returning ZERO for reading the next char - break; - - case ',': - // store the value, if any - StoreValue(ch, key, value, parent); - key.clear(); - ch = ReadChar(is); - break; - - case '\"': - ch = ReadString(is, value); // read a JSON string type - m_current = &value; - m_next = 0; - break; - - case '\'': - ch = ReadMemoryBuff(is, value); // read a memory buffer type - m_current = &value; - m_next = 0; - break; - - case ':': // key / value separator - m_current = &value; - m_current->SetLineNo(m_lineNo); - m_next = 0; - if (!parent.IsObject()) { - AddError(_T("\':\' can only used in object's values")); - } else if (!value.IsString()) { - AddError(_T("\':\' follows a value which is not of type \'string\'")); - } else if (!key.empty()) { - AddError(_T("\':\' not allowed where a \'name\' string was already available")); - } else { - // the string in 'value' is set as the 'key' - key = value.AsString(); - value.SetType(wxJSONTYPE_INVALID); - } - ch = ReadChar(is); - break; - - default: - // no special char: it is a literal or a number - // errors are checked in the 'ReadValue()' function. - m_current = &value; - m_current->SetLineNo(m_lineNo); - m_next = 0; - ch = ReadValue(is, ch, value); - break; - } // end switch - } while (ch >= 0); - - // the DoRead() should return when the close-object/array char is encontered - // if we are here, the EOF condition was encontered so one or more close-something - // characters are missing - if (parent.IsArray()) { - AddWarning(wxJSONREADER_MISSING, _T("\']\' missing at end of file")); - } else if (parent.IsObject()) { - AddWarning(wxJSONREADER_MISSING, _T("\'}\' missing at end of file")); - } else { wxJSON_ASSERT(0); - } - - // we store the value, as there is a missing close-object/array char - StoreValue(ch, key, value, parent); - - --m_level; - return ch; -} - -//! Store a value in the parent object. -/*! - The function is called by \c DoRead() when a the comma - or a close-object/array character is encontered and stores the current - value read by the parser in the parent object. - The function checks that \c value is not invalid and that \c key is - not an empty string if \c parent is an object. - - \param ch the character read: a comma or close objecty/array char - \param key the \b key string: must be empty if \c parent is an array - \param value the current JSON value to be stored in \c parent - \param parent the JSON value that is the parent of \c value. - \return none - */ -void -wxJSONReader::StoreValue(int ch, const wxString &key, wxJSONValue &value, wxJSONValue &parent) { - // if 'ch' == } or ] than value AND key may be empty when a open object/array - // is immediatly followed by a close object/array - // - // if 'ch' == , (comma) value AND key (for TypeMap) cannot be empty - // - wxLogTrace(traceMask, _T("(%s) ch=%d char=%c"), __PRETTY_FUNCTION__, ch, (char) ch); - wxLogTrace(traceMask, _T("(%s) value=%s"), __PRETTY_FUNCTION__, value.AsString().c_str()); - - m_current = 0; - m_next = &value; - m_lastStored = 0; - m_next->SetLineNo(-1); - - if (!value.IsValid() && key.empty()) { - // OK, if the char read is a close-object or close-array - if (ch == '}' || ch == ']') { - m_lastStored = 0; - wxLogTrace(traceMask, _T("(%s) key and value are empty, returning"), - __PRETTY_FUNCTION__); - } else { - AddError(_T("key or value is missing for JSON value")); - } - } else { - // key or value are not empty - if (parent.IsObject()) { - if (!value.IsValid()) { - AddError(_T("cannot store the value: \'value\' is missing for JSON object type")); - } else if (key.empty()) { - AddError(_T("cannot store the value: \'key\' is missing for JSON object type")); - } else { - // OK, adding the value to parent key/value map - wxLogTrace(traceMask, _T("(%s) adding value to key:%s"), - __PRETTY_FUNCTION__, key.c_str()); - parent[key] = value; - m_lastStored = &(parent[key]); - m_lastStored->SetLineNo(m_lineNo); - } - } else if (parent.IsArray()) { - if (!value.IsValid()) { - AddError(_T("cannot store the item: \'value\' is missing for JSON array type")); - } - if (!key.empty()) { - AddError(_T("cannot store the item: \'key\' (\'%s\') is not permitted in JSON array type"), key); - } - wxLogTrace(traceMask, _T("(%s) appending value to parent array"), - __PRETTY_FUNCTION__); - parent.Append(value); - const wxJSONInternalArray *arr = wxJSONValueAsArray(parent);wxJSON_ASSERT(arr); - m_lastStored = &(arr->Last()); - m_lastStored->SetLineNo(m_lineNo); - } else { wxJSON_ASSERT(0); // should never happen - } - } - value.SetType(wxJSONTYPE_INVALID); - value.ClearComments(); -} - -//! Add a error message to the error's array -/*! - The overloaded versions of this function add an error message to the - error's array stored in \c m_errors. - The error message is formatted as follows: - - \code - Error: line xxx, col xxx - - \endcode - - The \c msg parameter is the description of the error; line's and column's - number are automatically added by the functions. - The \c fmt parameter is a format string that has the same syntax as the \b printf - function. - Note that it is the user's responsability to provide a format string suitable - with the arguments: another string or a character. - */ -void -wxJSONReader::AddError(const wxString &msg) { - wxString err; - err.Printf(_T("Error: line %d, col %d - %s"), m_lineNo, m_colNo, msg.c_str()); - - wxLogTrace(traceMask, _T("(%s) %s"), __PRETTY_FUNCTION__, err.c_str()); - - if ((int) m_errors.size() < m_maxErrors) { - m_errors.Add(err); - } else if ((int) m_errors.size() == m_maxErrors) { - m_errors.Add(_T("ERROR: too many error messages - ignoring further errors")); - } - // else if ( m_errors > m_maxErrors ) do nothing, thus ignore the error message -} - -//! \overload AddError( const wxString& ) -void -wxJSONReader::AddError(const wxString &fmt, const wxString &str) { - wxString s; - s.Printf(fmt.c_str(), str.c_str()); - AddError(s); -} - -//! \overload AddError( const wxString& ) -void -wxJSONReader::AddError(const wxString &fmt, wxChar c) { - wxString s; - s.Printf(fmt.c_str(), c); - AddError(s); -} - -//! Add a warning message to the warning's array -/*! - The warning description is as follows: - \code - Warning: line xxx, col xxx - - \endcode - - Warning messages are generated by the parser when the JSON - text that has been read is not well-formed but the - error is not fatal and the parser recognizes the text - as an extension to the JSON standard (see the parser's ctor - for more info about wxJSON extensions). - - Note that the parser has to be constructed with a flag that - indicates if each individual wxJSON extension is on. - If the warning message is related to an extension that is not - enabled in the parser's \c m_flag data member, this function - calls AddError() and the warning message becomes an error - message. - The \c type parameter is one of the same constants that - specify the parser's extensions. - If type is ZERO than the function always adds a warning - */ -void -wxJSONReader::AddWarning(int type, const wxString &msg) { - // if 'type' AND 'm_flags' == 1 than the extension is - // ON. Otherwise it is OFF anf the function calls AddError() - if (type != 0) { - if ((type & m_flags) == 0) { - AddError(msg); - return; - } - } - - wxString err; - err.Printf(_T("Warning: line %d, col %d - %s"), m_lineNo, m_colNo, msg.c_str()); - - wxLogTrace(traceMask, _T("(%s) %s"), __PRETTY_FUNCTION__, err.c_str()); - if ((int) m_warnings.size() < m_maxErrors) { - m_warnings.Add(err); - } else if ((int) m_warnings.size() == m_maxErrors) { - m_warnings.Add(_T("Error: too many warning messages - ignoring further warnings")); - } - // else do nothing, thus ignore the warning message -} - -//! Skip all whitespaces. -/*! - The function reads characters from the input text - and returns the first non-whitespace character read or -1 - if EOF. - Note that the function does not rely on the \b isspace function - of the C library but checks the space constants: space, TAB and - LF. - */ -int -wxJSONReader::SkipWhiteSpace(wxInputStream &is) { - // just read one byte at a time and check for whitespaces - int ch; - do { - ch = ReadChar(is); - if (ch < 0) { - break; - } - } while (ch == ' ' || ch == '\n' || ch == '\t'); - wxLogTrace(traceMask, _T("(%s) end whitespaces line=%d col=%d"), - __PRETTY_FUNCTION__, m_lineNo, m_colNo); - return ch; -} - -//! Skip a comment -/*! - The function is called by DoRead() when a '/' (slash) character - is read from the input stream assuming that a C/C++ comment is starting. - Returns the first character that follows the comment or - -1 on EOF. - The function also adds a warning message because comments are not - valid JSON text. - The function also stores the comment, if any, in the \c m_comment data - member: it can be used by the DoRead() function if comments have to be - stored in the value they refer to. - */ -int -wxJSONReader::SkipComment(wxInputStream &is) { - static const wxChar *warn = - _T("Comments may be tolerated in JSON text but they are not part of JSON syntax"); - - // if it is a comment, then a warning is added to the array - // otherwise it is an error: values cannot start with a '/' - // read the char next to the first slash - int ch = ReadChar(is); - if (ch < 0) { - return -1; - } - - wxLogTrace(storeTraceMask, _T("(%s) start comment line=%d col=%d"), - __PRETTY_FUNCTION__, m_lineNo, m_colNo); - - // the temporary UTF-8/ANSI buffer that holds the comment string. This will be - // converted to a wxString object using wxString::FromUTF8() or From8BitData() - wxMemoryBuffer utf8Buff; - unsigned char c; - - if (ch == '/') { // C++ comment, read until end-of-line - // C++ comment strings are in UTF-8 format. we store all - // UTF-8 code units until the first LF or CR+LF - AddWarning(wxJSONREADER_ALLOW_COMMENTS, warn); - m_commentLine = m_lineNo; - utf8Buff.AppendData("//", 2); - - while (ch >= 0) { - if (ch == '\n') { - break; - } - if (ch == '\r') { - ch = PeekChar(is); - if (ch == '\n') { - ch = ReadChar(is); - } - break; - } else { - // store the char in the UTF8 temporary buffer - c = (unsigned char) ch; - utf8Buff.AppendByte(c); - } - ch = ReadChar(is); - } - // now convert the temporary UTF-8 buffer - m_comment = wxString::FromUTF8((const char *) utf8Buff.GetData(), - utf8Buff.GetDataLen()); - } - - // check if a C-style comment - else if (ch == '*') { // C-style comment - AddWarning(wxJSONREADER_ALLOW_COMMENTS, warn); - m_commentLine = m_lineNo; - utf8Buff.AppendData("/*", 2); - while (ch >= 0) { - // check the END-COMMENT chars ('*/') - if (ch == '*') { - ch = PeekChar(is); - if (ch == '/') { - ch = ReadChar(is); // read the '/' char - ch = ReadChar(is); // read the next char that will be returned - utf8Buff.AppendData("*/", 2); - break; - } - } - // store the char in the UTF8 temporary buffer - c = (unsigned char) ch; - utf8Buff.AppendByte(c); - ch = ReadChar(is); - } - // now convert the temporary buffer in a wxString object - if (m_noUtf8) { - m_comment = wxString::From8BitData((const char *) utf8Buff.GetData(), - utf8Buff.GetDataLen()); - } else { - m_comment = wxString::FromUTF8((const char *) utf8Buff.GetData(), - utf8Buff.GetDataLen()); - } - } else { // it is not a comment, return the character next the first '/' - AddError(_T("Strange '/' (did you want to insert a comment?)")); - // we read until end-of-line OR end of C-style comment OR EOF - // because a '/' should be a start comment - while (ch >= 0) { - ch = ReadChar(is); - if (ch == '*' && PeekChar(is) == '/') { - break; - } - if (ch == '\n') { - break; - } - } - // read the next char that will be returned - ch = ReadChar(is); - } - wxLogTrace(traceMask, _T("(%s) end comment line=%d col=%d"), - __PRETTY_FUNCTION__, m_lineNo, m_colNo); - wxLogTrace(storeTraceMask, _T("(%s) end comment line=%d col=%d"), - __PRETTY_FUNCTION__, m_lineNo, m_colNo); - wxLogTrace(storeTraceMask, _T("(%s) comment=%s"), - __PRETTY_FUNCTION__, m_comment.c_str()); - return ch; -} - -//! Read a string value -/*! - The function reads a string value from input stream and it is - called by the \c DoRead() function when it enconters the - double quote characters. - The function read all bytes up to the next double quotes - (unless it is escaped) and stores them in a temporary UTF-8 - memory buffer. - Also, the function processes the escaped characters defined - in the JSON syntax. - - Next, the function tries to convert the UTF-8 buffer to a - \b wxString object using the \b wxString::FromUTF8 function. - Depending on the build mode, we can have the following: - \li in Unicode the function always succeeds, provided that the - buffer contains valid UTF-8 code units. - - \li in ANSI builds the conversion may fail because of the presence of - unrepresentable characters in the current locale. In this case, - the default behaviour is to perform a char-by-char conversion; every - char that cannot be represented in the current locale is stored as - \e unicode \e escaped \e sequence - - \li in ANSI builds, if the reader is constructed with the wxJSONREADER_NOUTF8_STREAM - then no conversion takes place and the UTF-8 temporary buffer is simply - \b copied to the \b wxString object - - The string is, finally, stored in the provided wxJSONValue argument - provided that it is empty or it contains a string value. - This is because the parser class recognizes multi-line strings - like the following one: - \code - [ - "This is a very long string value which is splitted into more" - "than one line because it is more human readable" - ] - \endcode - Because of the lack of the value separator (,) the parser - assumes that the string was splitted into several double-quoted - strings. - If the value does not contain a string then an error is - reported. - Splitted strings cause the parser to report a warning. - */ -int -wxJSONReader::ReadString(wxInputStream &is, wxJSONValue &val) { - // the char last read is the opening qoutes (") - - wxMemoryBuffer utf8Buff; - char ues[8]; // stores a Unicode Escaped Esquence: \uXXXX - - int ch = 0; - while (ch >= 0) { - ch = ReadChar(is); - unsigned char c = (unsigned char) ch; - if (ch == '\\') { // an escape sequence - ch = ReadChar(is); - switch (ch) { - case -1: // EOF - break; - case 't': - utf8Buff.AppendByte('\t'); - break; - case 'n': - utf8Buff.AppendByte('\n'); - break; - case 'b': - utf8Buff.AppendByte('\b'); - break; - case 'r': - utf8Buff.AppendByte('\r'); - break; - case '\"': - utf8Buff.AppendByte('\"'); - break; - case '\\': - utf8Buff.AppendByte('\\'); - break; - case '/': - utf8Buff.AppendByte('/'); - break; - case 'f': - utf8Buff.AppendByte('\f'); - break; - case 'u': - ch = ReadUES(is, ues); - if (ch < 0) { // if EOF, returns - return ch; - } - // append the escaped character to the UTF8 buffer - AppendUES(utf8Buff, ues); - // many thanks to Bryan Ashby who discovered this bug - continue; - // break; - default: - AddError(_T("Unknow escaped character \'\\%c\'"), ch); - } - } else { - // we have read a non-escaped character so we have to append it to - // the temporary UTF-8 buffer until the next quote char - // URDB V3 has double quotes embedded within JSON string - // handle non-escaped double quotes in JSON (i.e. ends string at ",) - if (ch == '\"') { - if (m_skip_string_double_quotes) { - int pc = PeekChar(is); - if (pc == ':') // handles "name": value - break; - else if (pc == ',') // handle "M","t", r end of string is ",\n - { - ch = ReadChar(is); //',' - pc = PeekChar(is); - if (pc == '\n') // actual end of string - { - is.Ungetch(','); - break; - } else { - //utf8Buff.AppendByte('\\'); - utf8Buff.AppendByte('\"'); - } - } - //else - // utf8Buff.AppendByte('\\'); - } else { - break; - } - } - //if ( ch == '\"' ) { - // break; - //} - utf8Buff.AppendByte(c); - } - } - - // if UTF-8 conversion is disabled (ANSI builds only) we just copy the - // bit data to a wxString object - wxString s; - if (m_noUtf8) { - s = wxString::From8BitData((const char *) utf8Buff.GetData(), utf8Buff.GetDataLen()); - } else { - // perform UTF-8 conversion - // first we check that the UTF-8 buffer is correct, i.e. it contains valid - // UTF-8 code points. - // this works in both ANSI and Unicode builds. - size_t convLen = wxConvUTF8.ToWChar(0, // wchar_t destination - 0, // size_t destLenght - (const char *) utf8Buff.GetData(), // char_t source - utf8Buff.GetDataLen()); // size_t sourceLenght - - if (convLen == wxCONV_FAILED) { - AddError(_T("String value: the UTF-8 stream is invalid")); - s.append(_T("")); - } else { -#if defined( wxJSON_USE_UNICODE ) - // in Unicode just convert to wxString - s = wxString::FromUTF8((const char *) utf8Buff.GetData(), utf8Buff.GetDataLen()); -#else - // in ANSI, the conversion may fail and an empty string is returned - // in this case, the reader do a char-by-char conversion storing - // unicode escaped sequences of unrepresentable characters - s = wxString::FromUTF8( (const char*) utf8Buff.GetData(), utf8Buff.GetDataLen()); - if ( s.IsEmpty() ) { - int r = ConvertCharByChar( s, utf8Buff ); // return number of escaped sequences - if ( r > 0 ) { - AddWarning( 0, _T( "The string value contains unrepresentable Unicode characters")); - } - } -#endif - } - } - wxLogTrace(traceMask, _T("(%s) line=%d col=%d"), - __PRETTY_FUNCTION__, m_lineNo, m_colNo); - wxLogTrace(traceMask, _T("(%s) string read=%s"), - __PRETTY_FUNCTION__, s.c_str()); - wxLogTrace(traceMask, _T("(%s) value=%s"), - __PRETTY_FUNCTION__, val.AsString().c_str()); - - // now assign the string to the JSON-value 'value' - // must check that: - // 'value' is empty - // 'value' is a string; concatenate it but emit warning - if (!val.IsValid()) { - wxLogTrace(traceMask, _T("(%s) assigning the string to value"), __PRETTY_FUNCTION__); - val = s; - } else if (val.IsString()) { - AddWarning(wxJSONREADER_MULTISTRING, - _T("Multiline strings are not allowed by JSON syntax")); - wxLogTrace(traceMask, _T("(%s) concatenate the string to value"), __PRETTY_FUNCTION__); - val.Cat(s); - } else { - AddError(_T("String value \'%s\' cannot follow another value"), s); - } - - // store the input text's line number when the string was stored in 'val' - val.SetLineNo(m_lineNo); - - // read the next char after the closing quotes and returns it - if (ch >= 0) { - ch = ReadChar(is); - } - return ch; -} - -//! Reads a token string -/*! - This function is called by the ReadValue() when the - first character encontered is not a special char - and it is not a double-quote. - The only possible type is a literal or a number which - all lies in the US-ASCII charset so their UTF-8 encodeing - is the same as US-ASCII. - The function simply reads one byte at a time from the stream - and appends them to a \b wxString object. - Returns the next character read. - - A token cannot include \e unicode \e escaped \e sequences - so this function does not try to interpret such sequences. - - @param is the input stream - @param ch the character read by DoRead - @param s the string object that contains the token read - @return -1 in case of errors or EOF - */ -int -wxJSONReader::ReadToken(wxInputStream &is, int ch, wxString &s) { - int nextCh = ch; - while (nextCh >= 0) { - switch (nextCh) { - case ' ': - case ',': - case ':': - case '[': - case ']': - case '{': - case '}': - case '\t': - case '\n': - case '\r': - case '\b': - wxLogTrace(traceMask, _T("(%s) line=%d col=%d"), - __PRETTY_FUNCTION__, m_lineNo, m_colNo); - wxLogTrace(traceMask, _T("(%s) token read=%s"), - __PRETTY_FUNCTION__, s.c_str()); - return nextCh; - break; - default: - s.Append((unsigned char) nextCh, 1); - break; - } - // read the next character - nextCh = ReadChar(is); - } - wxLogTrace(traceMask, _T("(%s) EOF on line=%d col=%d"), - __PRETTY_FUNCTION__, m_lineNo, m_colNo); - wxLogTrace(traceMask, _T("(%s) EOF - token read=%s"), - __PRETTY_FUNCTION__, s.c_str()); - return nextCh; -} - -//! Read a value from input stream -/*! - The function is called by DoRead() when it enconters a char that is - not a special char nor a double-quote. - It assumes that the string is a numeric value or a literal - boolean value and stores it in the wxJSONValue object \c val. - - The function also checks that \c val is of type wxJSONTYPE_INVALID otherwise - an error is reported becasue a value cannot follow another value: - maybe a (,) or (:) is missing. - - If the literal starts with a digit, a plus or minus sign, the function - tries to interpret it as a number. The following are tried by the function, - in this order: - - \li if the literal starts with a digit: signed integer, then unsigned integer - and finally double conversion is tried - \li if the literal starts with a minus sign: signed integer, then double - conversion is tried - \li if the literal starts with plus sign: unsigned integer - then double conversion is tried - - Returns the next character or -1 on EOF. - */ -int -wxJSONReader::ReadValue(wxInputStream &is, int ch, wxJSONValue &val) { - wxString s; - int nextCh = ReadToken(is, ch, s); - wxLogTrace(traceMask, _T("(%s) value=%s"), - __PRETTY_FUNCTION__, val.AsString().c_str()); - - if (val.IsValid()) { - AddError(_T("Value \'%s\' cannot follow a value: \',\' or \':\' missing?"), s); - return nextCh; - } - - // variables used for converting numeric values - bool r; - double d; -#if defined( wxJSON_64BIT_INT ) - wxInt64 i64; - wxUint64 ui64; -#else - unsigned long int ul; long int l; -#endif - - // first try the literal strings lowercase and nocase - if (s == _T("null")) { - val.SetType(wxJSONTYPE_NULL); - wxLogTrace(traceMask, _T("(%s) value = NULL"), __PRETTY_FUNCTION__); - return nextCh; - } else if (s.CmpNoCase(_T("null")) == 0) { - wxLogTrace(traceMask, _T("(%s) value = NULL"), __PRETTY_FUNCTION__); - AddWarning(wxJSONREADER_CASE, _T("the \'null\' literal must be lowercase")); - val.SetType(wxJSONTYPE_NULL); - return nextCh; - } else if (s == _T("true")) { - wxLogTrace(traceMask, _T("(%s) value = TRUE"), __PRETTY_FUNCTION__); - val = true; - return nextCh; - } else if (s.CmpNoCase(_T("true")) == 0) { - wxLogTrace(traceMask, _T("(%s) value = TRUE"), __PRETTY_FUNCTION__); - AddWarning(wxJSONREADER_CASE, _T("the \'true\' literal must be lowercase")); - val = true; - return nextCh; - } else if (s == _T("false")) { - wxLogTrace(traceMask, _T("(%s) value = FALSE"), __PRETTY_FUNCTION__); - val = false; - return nextCh; - } else if (s.CmpNoCase(_T("false")) == 0) { - wxLogTrace(traceMask, _T("(%s) value = FALSE"), __PRETTY_FUNCTION__); - AddWarning(wxJSONREADER_CASE, _T("the \'false\' literal must be lowercase")); - val = false; - return nextCh; - } - - // try to convert to a number if the token starts with a digit, a plus or a minus - // sign. The function first states what type of conversion are tested: - // 1. first signed integer (not if 'ch' == '+') - // 2. unsigned integer (not if 'ch' == '-') - // 3. finally double - bool tSigned = true, tUnsigned = true, tDouble = true; - switch (ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - // first try a signed integer, then a unsigned integer, then a double - break; - - case '+': - // the plus sign forces a unsigned integer - tSigned = false; - break; - - case '-': - // try signed and double - tUnsigned = false; - break; - default: - AddError(_T("Literal \'%s\' is incorrect (did you forget quotes?)"), s); - return nextCh; - } - - if (tSigned) { -#if defined( wxJSON_64BIT_INT) - r = Strtoll(s, &i64); - wxLogTrace(traceMask, _T("(%s) convert to wxInt64 result=%d"), - __PRETTY_FUNCTION__, r); - if (r) { - // store the value - val = i64; - return nextCh; - } -#else - r = s.ToLong( &l ); - wxLogTrace( traceMask, _T("(%s) convert to int result=%d"), - __PRETTY_FUNCTION__, r ); - if ( r ) { - // store the value - val = (int) l; - return nextCh; - } -#endif - } - - if (tUnsigned) { -#if defined( wxJSON_64BIT_INT) - r = Strtoull(s, &ui64); - wxLogTrace(traceMask, _T("(%s) convert to wxUint64 result=%d"), - __PRETTY_FUNCTION__, r); - if (r) { - // store the value - val = ui64; - return nextCh; - } -#else - r = s.ToULong( &ul ); - wxLogTrace( traceMask, _T("(%s) convert to int result=%d"), - __PRETTY_FUNCTION__, r ); - if ( r ) { - // store the value - val = (unsigned int) ul; - return nextCh; - } -#endif - } - - if (tDouble) { - r = s.ToDouble(&d); - wxLogTrace(traceMask, _T("(%s) convert to double result=%d"), - __PRETTY_FUNCTION__, r); - if (r) { - // store the value - val = d; - return nextCh; - } - } - - // the value is not syntactically correct - AddError(_T("Literal \'%s\' is incorrect (did you forget quotes?)"), s); - return nextCh; -} - -//! Read a 4-hex-digit unicode character. -/*! - The function is called by ReadString() when the \b \\u sequence is - encontered; the sequence introduces a control character in the form: - \code - \uXXXX - \endcode - where XXXX is a four-digit hex code.. - The function reads four chars from the input UTF8 stream by calling ReadChar() - four times: if EOF is encontered before reading four chars, -1 is - also returned and no sequence interpretation is performed. - The function stores the 4 hexadecimal digits in the \c uesBuffer parameter. - - Returns the character after the hex sequence or -1 if EOF. - - \b NOTICE: although the JSON syntax states that only control characters - are represented in this way, the wxJSON library reads and recognizes all - unicode characters in the BMP. - */ -int -wxJSONReader::ReadUES(wxInputStream &is, char *uesBuffer) { - int ch; - for (int i = 0; i < 4; i++) { - ch = ReadChar(is); - if (ch < 0) { - return ch; - } - uesBuffer[i] = (unsigned char) ch; - } - uesBuffer[4] = 0; // makes a ASCIIZ string - - return 0; -} - -//! The function appends a Unice Escaped Sequence to the temporary UTF8 buffer -/*! - This function is called by \c ReadString() when a \e unicode \e escaped - \e sequence is read from the input text as for example: - - \code - \u0001 - \endcode - - which represents a control character. - The \c uesBuffer parameter contains the 4 hexadecimal digits that are - read from \c ReadUES. - - The function tries to convert the 4 hex digits in a \b wchar_t character - which is appended to the memory buffer \c utf8Buff after converting it - to UTF-8. - - If the conversion from hexadecimal fails, the function does not - store the character in the UTF-8 buffer and an error is reported. - The function is the same in ANSI and Unicode. - Returns -1 if the buffer does not contain valid hex digits. - sequence. On success returns ZERO. - - @param utf8Buff the UTF-8 buffer to which the control char is written - @param uesBuffer the four-hex-digits read from the input text - @return ZERO on success, -1 if the four-hex-digit buffer cannot be converted - */ -int -wxJSONReader::AppendUES(wxMemoryBuffer &utf8Buff, const char *uesBuffer) { - unsigned long l; - int r = sscanf(uesBuffer, "%lx", &l); // r is the assigned items - if (r != 1) { - AddError(_T("Invalid Unicode Escaped Sequence")); - return -1; - } - wxLogTrace(traceMask, _T("(%s) unicode sequence=%s code=%ld"), - __PRETTY_FUNCTION__, uesBuffer, l); - - wchar_t ch = (wchar_t) l; - char buffer[16]; - size_t len = wxConvUTF8.FromWChar(buffer, 10, &ch, 1); - - // seems that the wxMBConv classes always appends a NULL byte to - // the converted buffer - if (len > 1) { - len = len - 1; - } - utf8Buff.AppendData(buffer, len); - - // sould never fail - wxASSERT(len != wxCONV_FAILED); - return 0; -} - -//! Store the comment string in the value it refers to. -/*! - The function searches a suitable value object for storing the - comment line that was read by the parser and temporarly - stored in \c m_comment. - The function searches the three values pointed to by: - \li \c m_next - \li \c m_current - \li \c m_lastStored - - The value that the comment refers to is: - - \li if the comment is on the same line as one of the values, the comment - refer to that value and it is stored as \b inline. - \li otherwise, if the comment flag is wxJSONREADER_COMMENTS_BEFORE, the comment lines - are stored in the value pointed to by \c m_next - \li otherwise, if the comment flag is wxJSONREADER_COMMENTS_AFTER, the comment lines - are stored in the value pointed to by \c m_current or m_latStored - - Note that the comment line is only stored if the wxJSONREADER_STORE_COMMENTS - flag was used when the parser object was constructed; otherwise, the - function does nothing and immediatly returns. - Also note that if the comment line has to be stored but the - function cannot find a suitable value to add the comment line to, - an error is reported (note: not a warning but an error). - */ -void -wxJSONReader::StoreComment(const wxJSONValue *parent) { - wxLogTrace(storeTraceMask, _T("(%s) m_comment=%s"), __PRETTY_FUNCTION__, m_comment.c_str()); - wxLogTrace(storeTraceMask, _T("(%s) m_flags=%d m_commentLine=%d"), - __PRETTY_FUNCTION__, m_flags, m_commentLine); - wxLogTrace(storeTraceMask, _T("(%s) m_current=%p"), __PRETTY_FUNCTION__, m_current); - wxLogTrace(storeTraceMask, _T("(%s) m_next=%p"), __PRETTY_FUNCTION__, m_next); - wxLogTrace(storeTraceMask, _T("(%s) m_lastStored=%p"), __PRETTY_FUNCTION__, m_lastStored); - - // first check if the 'store comment' bit is on - if ((m_flags & wxJSONREADER_STORE_COMMENTS) == 0) { - m_comment.clear(); - return; - } - - // check if the comment is on the same line of one of the - // 'current', 'next' or 'lastStored' value - if (m_current != 0) { - wxLogTrace(storeTraceMask, _T("(%s) m_current->lineNo=%d"), - __PRETTY_FUNCTION__, m_current->GetLineNo()); - if (m_current->GetLineNo() == m_commentLine) { - wxLogTrace(storeTraceMask, _T("(%s) comment added to \'m_current\' INLINE"), - __PRETTY_FUNCTION__); - m_current->AddComment(m_comment, wxJSONVALUE_COMMENT_INLINE); - m_comment.clear(); - return; - } - } - if (m_next != 0) { - wxLogTrace(storeTraceMask, _T("(%s) m_next->lineNo=%d"), - __PRETTY_FUNCTION__, m_next->GetLineNo()); - if (m_next->GetLineNo() == m_commentLine) { - wxLogTrace(storeTraceMask, _T("(%s) comment added to \'m_next\' INLINE"), - __PRETTY_FUNCTION__); - m_next->AddComment(m_comment, wxJSONVALUE_COMMENT_INLINE); - m_comment.clear(); - return; - } - } - if (m_lastStored != 0) { - wxLogTrace(storeTraceMask, _T("(%s) m_lastStored->lineNo=%d"), - __PRETTY_FUNCTION__, m_lastStored->GetLineNo()); - if (m_lastStored->GetLineNo() == m_commentLine) { - wxLogTrace(storeTraceMask, _T("(%s) comment added to \'m_lastStored\' INLINE"), - __PRETTY_FUNCTION__); - m_lastStored->AddComment(m_comment, wxJSONVALUE_COMMENT_INLINE); - m_comment.clear(); - return; - } - } - - // if comment is BEFORE, store the comment in the 'm_next' - // or 'm_current' value - // if comment is AFTER, store the comment in the 'm_lastStored' - // or 'm_current' value - - if (m_flags & wxJSONREADER_COMMENTS_AFTER) { // comment AFTER - if (m_current) { - if (m_current == parent || !m_current->IsValid()) { - AddError(_T("Cannot find a value for storing the comment (flag AFTER)")); - } else { - wxLogTrace(storeTraceMask, _T("(%s) comment added to m_current (AFTER)"), - __PRETTY_FUNCTION__); - m_current->AddComment(m_comment, wxJSONVALUE_COMMENT_AFTER); - } - } else if (m_lastStored) { - wxLogTrace(storeTraceMask, _T("(%s) comment added to m_lastStored (AFTER)"), - __PRETTY_FUNCTION__); - m_lastStored->AddComment(m_comment, wxJSONVALUE_COMMENT_AFTER); - } else { - wxLogTrace(storeTraceMask, - _T("(%s) cannot find a value for storing the AFTER comment"), __PRETTY_FUNCTION__); - AddError(_T("Cannot find a value for storing the comment (flag AFTER)")); - } - } else { // comment BEFORE can only be added to the 'next' value - if (m_next) { - wxLogTrace(storeTraceMask, _T("(%s) comment added to m_next (BEFORE)"), - __PRETTY_FUNCTION__); - m_next->AddComment(m_comment, wxJSONVALUE_COMMENT_BEFORE); - } else { - // cannot find a value for storing the comment - AddError(_T("Cannot find a value for storing the comment (flag BEFORE)")); - } - } - m_comment.clear(); -} - -//! Return the number of bytes that make a character in stream input -/*! - This function returns the number of bytes that represent a unicode - code point in various encoding. - For example, if the input stream is UTF-32 the function returns 4. - Because the only recognized format for streams is UTF-8 the function - just calls UTF8NumBytes() and returns. - The function is, actually, not used at all. - - */ -int -wxJSONReader::NumBytes(char ch) { - int n = UTF8NumBytes(ch); - return n; -} - -//! Compute the number of bytes that makes a UTF-8 encoded wide character. -/*! - The function counts the number of '1' bit in the character \c ch and - returns it. - The UTF-8 encoding specifies the number of bytes needed by a wide character - by coding it in the first byte. See below. - - Note that if the character does not contain a valid UTF-8 encoding - the function returns -1. - - \code - UCS-4 range (hex.) UTF-8 octet sequence (binary) - ------------------- ----------------------------- - 0000 0000-0000 007F 0xxxxxxx - 0000 0080-0000 07FF 110xxxxx 10xxxxxx - 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx - 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx - \endcode - */ -int -wxJSONReader::UTF8NumBytes(char ch) { - int num = 0; // the counter of '1' bits - for (int i = 0; i < 8; i++) { - if ((ch & 0x80) == 0) { - break; - } - ++num; - ch = ch << 1; - } - - // note that if the char contains more than six '1' bits it is not - // a valid UTF-8 encoded character - if (num > 6) { - num = -1; - } else if (num == 0) { - num = 1; - } - return num; -} - -//! Convert a UTF-8 memory buffer one char at a time -/*! - This function is used in ANSI mode when input from a stream is in UTF-8 - format and the UTF-8 buffer read cannot be converted to the locale - wxString object. - The function performs a char-by-char conversion of the buffer and appends - every representable character to the string \c s. - Characters that cannot be represented are stored as \e unicode \e escaped - \e sequences in the form: - \code - \uXXXX - \endcode - where XXXX is a for-hex-digits Unicode code point. - The function returns the number of characters that cannot be represented - in the current locale. - */ -int -wxJSONReader::ConvertCharByChar(wxString &s, const wxMemoryBuffer &utf8Buffer) { - size_t len = utf8Buffer.GetDataLen(); - char *buff = (char *) utf8Buffer.GetData(); - char *buffEnd = buff + len; - - int result = 0; - char temp[16]; // the UTF-8 code-point - - while (buff < buffEnd) { - temp[0] = *buff; // the first UTF-8 code-unit - // compute the number of code-untis that make one UTF-8 code-point - int numBytes = NumBytes(*buff); - ++buff; - for (int i = 1; i < numBytes; i++) { - if (buff >= buffEnd) { - break; - } - temp[i] = *buff; // the first UTF-8 code-unit - ++buff; - } - //if ( buff >= buffEnd ) { - // break; - //} - // now convert 'temp' to a wide-character - wchar_t dst[10]; - size_t outLength = wxConvUTF8.ToWChar(dst, 10, temp, numBytes); - - // now convert the wide char to a locale dependent character - // len = wxConvLocal.FromWChar( temp, 16, dst, outLength ); - // len = wxConviso8859_1.FromWChar( temp, 16, dst, outLength ); - len = wxConvLibc.FromWChar(temp, 16, dst, outLength); - if (len == wxCONV_FAILED) { - ++result; - wxString t; - t.Printf(_T("\\u%04X"), (int) dst[0]); - s.Append(t); - } else { - s.Append(temp[0], 1); - } - } // end while - return result; -} - -//! Read a memory buffer type -/*! - This function is called by DoRead() when the single-quote character is - encontered which starts a \e memory \e buffer type. - This type is a \b wxJSON extension so the function emits a warning - when such a type encontered. - If the reader is constructed without the \c wxJSONREADER_MEMORYBUFF flag - then the warning becomes an error. - To know more about this JSON syntax extension read \ref wxjson_tutorial_memorybuff - - @param is the input stream - @param val the JSON value that will hold the memory buffer value - @return the last char read or -1 in case of EOF - */ - -union byte { - unsigned char c[2]; - short int b; -}; - -int -wxJSONReader::ReadMemoryBuff(wxInputStream &is, wxJSONValue &val) { - static const wxChar *membuffError = _T("the \'memory buffer\' type contains %d invalid digits"); - - AddWarning(wxJSONREADER_MEMORYBUFF, _T("the \'memory buffer\' type is not valid JSON text")); - - wxMemoryBuffer buff; - int ch = 0; - int errors = 0; - unsigned char byte = 0; - while (ch >= 0) { - ch = ReadChar(is); - if (ch < 0) { - break; - } - if (ch == '\'') { - break; - } - // the conversion is done two chars at a time - unsigned char c1 = (unsigned char) ch; - ch = ReadChar(is); - if (ch < 0) { - break; - } - unsigned char c2 = (unsigned char) ch; - c1 -= '0'; - c2 -= '0'; - if (c1 > 9) { - c1 -= 7; - } - if (c2 > 9) { - c2 -= 7; - } - if (c1 > 15) { - ++errors; - } else if (c2 > 15) { - ++errors; - } else { - byte = (c1 * 16) + c2; - buff.AppendByte(byte); - } - } // end while - - if (errors > 0) { - wxString err; - err.Printf(membuffError, errors); - AddError(err); - } - - // now assign the memory buffer object to the JSON-value 'value' - // must check that: - // 'value' is invalid OR - // 'value' is a memory buffer; concatenate it - if (!val.IsValid()) { - wxLogTrace(traceMask, _T("(%s) assigning the memory buffer to value"), __PRETTY_FUNCTION__); - val = buff; - } else if (val.IsMemoryBuff()) { - wxLogTrace(traceMask, _T("(%s) concatenate memory buffer to value"), __PRETTY_FUNCTION__); - val.Cat(buff); - } else { - AddError(_T("Memory buffer value cannot follow another value")); - } - - // store the input text's line number when the string was stored in 'val' - val.SetLineNo(m_lineNo); - - // read the next char after the closing quotes and returns it - if (ch >= 0) { - ch = ReadChar(is); - } - return ch; -} - -#if defined( wxJSON_64BIT_INT ) -//! Converts a decimal string to a 64-bit signed integer -/*! - This function implements a simple variant - of the \b strtoll C-library function. - I needed this implementation because the wxString::To(U)LongLong - function does not work on my system: - - \li GNU/Linux Fedora Core 6 - \li GCC version 4.1.1 - \li libc.so.6 - - The wxWidgets library (actually I have installed version 2.8.7) - relies on \b strtoll in order to do the conversion from a string - to a long long integer but, in fact, it does not work because - the 'wxHAS_STRTOLL' macro is not defined on my system. - The problem only affects the Unicode builds while it seems - that the wxString::To(U)LongLong function works in ANSI builds. - - Note that this implementation is not a complete substitute of the - strtoll function because it only converts decimal strings (only base - 10 is implemented). - - @param str the string that contains the decimal literal - @param i64 the pointer to long long which holds the converted value - - @return TRUE if the conversion succeeds - */ -bool -wxJSONReader::Strtoll(const wxString &str, wxInt64 *i64) { - wxChar sign = ' '; - wxUint64 ui64; - bool r = DoStrto_ll(str, &ui64, &sign); - - // check overflow for signed long long - switch (sign) { - case '-': - if (ui64 > (wxUint64) LLONG_MAX + 1) { - r = false; - } else { - *i64 = (wxInt64) (ui64 * -1); - } - break; - - // case '+' : - default: - if (ui64 > LLONG_MAX) { - r = false; - } else { - *i64 = (wxInt64) ui64; - } - break; - } - return r; -} - -//! Converts a decimal string to a 64-bit unsigned integer. -/*! - Similar to \c Strtoll but for unsigned integers - */ -bool -wxJSONReader::Strtoull(const wxString &str, wxUint64 *ui64) { - wxChar sign = ' '; - bool r = DoStrto_ll(str, ui64, &sign); - if (sign == '-') { - r = false; - } - return r; -} - -//! Perform the actual conversion from a string to a 64-bit integer -/*! - This function is called internally by the \c Strtoll and \c Strtoull functions - and it does the actual conversion. - The function is also able to check numeric overflow. - - @param str the string that has to be converted - @param ui64 the pointer to a unsigned long long that holds the converted value - @param sign the pointer to a wxChar character that will get the sign of the literal string, if any - @return TRUE if the conversion succeeds - */ -bool -wxJSONReader::DoStrto_ll(const wxString &str, wxUint64 *ui64, wxChar *sign) { - // the conversion is done by multiplying the individual digits - // in reverse order to the corresponding power of 10 - // - // 10's power: 987654321.9876543210 - // - // LLONG_MAX: 9223372036854775807 - // LLONG_MIN: -9223372036854775808 - // ULLONG_MAX: 18446744073709551615 - // - // the function does not take into account the sign: only a - // unsigned long long int is returned - - int maxDigits = 20; // 20 + 1 (for the sign) - - wxUint64 power10[] = { - wxULL(1), - wxULL(10), - wxULL(100), - wxULL(1000), - wxULL(10000), - wxULL(100000), - wxULL(1000000), - wxULL(10000000), - wxULL(100000000), - wxULL(1000000000), - wxULL(10000000000), - wxULL(100000000000), - wxULL(1000000000000), - wxULL(10000000000000), - wxULL(100000000000000), - wxULL(1000000000000000), - wxULL(10000000000000000), - wxULL(100000000000000000), - wxULL(1000000000000000000), - wxULL(10000000000000000000) - }; - - wxUint64 temp1 = wxULL(0); // the temporary converted integer - - int strLen = str.length(); - if (strLen == 0) { - // an empty string is converted to a ZERO value: the function succeeds - *ui64 = wxLL(0); - return true; - } - - int index = 0; - wxChar ch = str[0]; - if (ch == '+' || ch == '-') { - *sign = ch; - ++index; - ++maxDigits; - } - - if (strLen > maxDigits) { - return false; - } - - // check the overflow: check the string length and the individual digits - // of the string; the overflow is checked for unsigned long long - if (strLen == maxDigits) { - wxString uLongMax(_T("18446744073709551615")); - int j = 0; - for (int i = index; i < strLen - 1; i++) { - ch = str[i]; - if (ch < '0' || ch > '9') { - return false; - } - if (ch > uLongMax[j]) { - return false; - } - if (ch < uLongMax[j]) { - break; - } - ++j; - } - } - - // get the digits in the reverse order and multiply them by the - // corresponding power of 10 - int exponent = 0; - for (int i = strLen - 1; i >= index; i--) { - wxChar ch_tmp = str[i]; - if (ch_tmp < '0' || ch_tmp > '9') { - return false; - } - ch_tmp = ch_tmp - '0'; - // compute the new temporary value - temp1 += ch_tmp * power10[exponent]; - ++exponent; - } - *ui64 = temp1; - return true; -} - -#endif // defined( wxJSON_64BIT_INT ) - -/* -{ -} -*/ diff --git a/src/jsonval.cpp b/src/jsonval.cpp deleted file mode 100644 index b5f778fb..00000000 --- a/src/jsonval.cpp +++ /dev/null @@ -1,3329 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: jsonval.cpp -// Purpose: the wxJSON class that holds a JSON value -// Author: Luciano Cattani -// Created: 2007/10/01 -// RCS-ID: $Id: jsonval.cpp,v 1.12 2008/03/06 10:25:18 luccat Exp $ -// Copyright: (c) 2007 Luciano Cattani -// Licence: wxWidgets licence -///////////////////////////////////////////////////////////////////////////// - -// For compilers that support precompilation, includes "wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#include -#include -#include - -#include "wex/jsonval.h" - -WX_DEFINE_OBJARRAY(wxJSONInternalArray); - -#if wxUSE_LOG_TRACE -// the trace mask used in wxLogTrace() function -// static const wxChar* traceMask = wxT("jsonval"); -static const wxChar* traceMask = wxT("jsonval"); -static const wxChar* compareTraceMask = wxT("sameas"); -static const wxChar* cowTraceMask = wxT("traceCOW"); -#endif - -double json_double(const wxJSONValue &jv, double defaultval, bool *Exists) { - if (jv.IsNull()) { - //if (Exists) *Exists = false; - return defaultval; - } - - if (jv.IsString()) { - double d; - if (jv.AsString().ToDouble(&d)) { - if (Exists) *Exists = true; - return d; - } - } - - if (jv.IsDouble()) { - if (Exists) *Exists = true; - return jv.AsDouble(); - } - - if (jv.IsInt()) { - if (Exists) *Exists = true; - return (double) jv.AsInt(); - } - - if (jv.IsLong()) { - if (Exists) *Exists = true; - return (double) jv.AsLong(); - } - - //if (Exists) *Exists = false; - return defaultval; -} - -int json_integer(const wxJSONValue &jv, int defaultval, bool *Exists) { - if (jv.IsNull()) { - //if (Exists) *Exists = false; - return defaultval; - } - - if (jv.IsString()) { - long l; - if (jv.AsString().ToLong(&l)) { - if (Exists) *Exists = true; - return (int) l; - } - } - - if (jv.IsInt()) { - if (Exists) *Exists = true; - return (int) jv.AsInt(); - } - - if (jv.IsLong()) { - if (Exists) *Exists = true; - return (int) jv.AsLong(); - } - - //if (Exists) *Exists = false; - return defaultval; -} - -wxString json_string(const wxJSONValue &jv, const wxString &defaultval, bool *Exists) { - if (jv.IsNull()) { - //if (Exists) *Exists = false; - return defaultval; - } - - if (jv.IsString()) { - if (Exists) *Exists = true; - return jv.AsString(); - } - - if (jv.IsCString()) { - if (Exists) *Exists = true; - return wxString(jv.AsCString()); - } - - //if (Exists) *Exists = false; - return defaultval; -} - -/******************************************************************* - - class wxJSONRefData - - *******************************************************************/ - -/*! \class wxJSONRefData - \brief The reference counted JSON value data (internal use). - - Starting from version 0.4, the JSON value class use the reference - counting tecnique (also know as \e copy-on-write) described in the - \b wxWidgets documentation in order to speed up processing. - The class is used internally by the wxJSONValue class which does - all processing. - To know more about COW see \ref json_internals_cow - */ - -#if defined( WXJSON_USE_VALUE_COUNTER ) -// The progressive counter (used for debugging only) -int wxJSONRefData::sm_progr = 1; -#endif - -//! Constructor. -wxJSONRefData::wxJSONRefData() { - m_lineNo = -1; - m_refCount = 1; - m_memBuff = 0; - -#if defined( WXJSON_USE_VALUE_COUNTER ) - m_progr = sm_progr; - ++sm_progr; - wxLogTrace( traceMask, wxT("(%s) JSON refData ctor progr=%d"), - __PRETTY_FUNCTION__, m_progr); -#endif -} - -// Dtor -wxJSONRefData::~wxJSONRefData() { - if (m_memBuff) { - delete m_memBuff; - } -} - -// Return the number of objects that reference this data. -int -wxJSONRefData::GetRefCount() const { - return m_refCount; -} - -/******************************************************************* - - class wxJSONValue - - *******************************************************************/ - -/*! \class wxJSONValue - \brief The JSON value class implementation. - - This class holds a JSON value which may be of variuos types (see the - wxJSONType constants for a description of the types). - To know more about the internal representation of JSON values see - \ref pg_json_internals. - - Starting from version 0.5 the wxJSON library supports 64-bits integers on - platforms that have native support for very large integers. - Note that the integer type is still stored as a generic wxJSONTYPE_(U)INT - constant regardless the size of the value but the JSON value class defines - functions in order to let the user know if an integer value fits in 16, 32 - or 64 bit integer. - To know more about 64-bits integer support see \ref json_internals_integer - - Storing values in a JSON value object of this class is very simple. - The following is an example: - \code - wxJSONValue v( wxT( "A string")); // store a string value in the object - wxString s = v.AsString(); // get the string value - - v = 12; // now 'v' contains an integer value - int i = v.AsInt(); // get the integer - \endcode - - \par The C-string JSON value object - - The wxJSONValue(const wxChar*) ctor allows you to create a JSON value - object that contains a string value which is stored as a - \e pointer-to-static-string. - Beware that this ctor DOES NOT copy the string: it only stores the - pointer in a data member and the pointed-to buffer is not deleted - by the dtor. - If the string is not static you have to use the wxJSONValue(const wxString&) - constructor. - - Also note that this does NOT mean that the value stored in this JSON - object cannot change: you can assign whatever other value you want, - an integer, a double or an array of values. - What I intended is that the pointed-to string must exist for the lifetime - of the wxJSONValue object. - The following code is perfectly legal: - \code - wxJSONvalue aString( "this is a static string" ); - aString = 10; - \endcode - To know more about this topic see \ref json_internals_cstring. - - Starting from version 1.3 the class can hold binary memory buffers - as an extension to the JSON syntax. Memory buffers are stored as - \b wxMemoryBuffer objects which contain binary data. The class - uses reference counting for the copy and assignment operation but - it is not a \e copy-on-write structure. - To know more about memory buffers read \ref wxjson_tutorial_memorybuff - - \sa the \ref wxjson_tutorial. - */ - -#if defined( WXJSON_USE_VALUE_COUNTER ) -// The progressive counter (used for debugging only) -int wxJSONValue::sm_progr = 1; -#endif - -//! Constructors. -/*! - The overloaded constructors allow the user to construct a JSON value - object that holds the specified value and type of value. - The default ctor construct a valid JSON object that constains a \b null - value. - - If you want to create an \b invalid JSON value object you have to use the - \c wxJSONValue( wxJSONTYPE_INVALID ) ctor. - Note that this object is not a valid JSON value - to know more about this - topic see the SetType() function. - - To create an empty array or key/value map use the following: - \code - wxJSONvalue v1( wxJSONTYPE_ARRAY ); - wxJSONvalue v2( wxJSONTYPE_OBJECT ); - \endcode - */ -wxJSONValue::wxJSONValue() { - m_refData = 0; - Init(wxJSONTYPE_NULL); -} - -//! Initialize the JSON value class. -/*! - The function is called by the ctors and allocates a new instance of - the wxJSONRefData class and sets the type of the JSON value. - Note that only the type is set, not the value. - Also note that this function may be called from other memberfunctions - if the \c m_refData data member is NULL. - */ -wxJSONRefData * -wxJSONValue::Init(wxJSONType type) { - wxJSONRefData *data = GetRefData(); - if (data != 0) { - UnRef(); - } - - // we allocate a new instance of the referenced data - data = new wxJSONRefData();wxJSON_ASSERT(data); - - // in release builds we do not have ASSERT so we check 'data' before - // using it - if (data) { - data->m_type = type; - data->m_commentPos = wxJSONVALUE_COMMENT_BEFORE; - } - SetRefData(data); - -#if defined( WXJSON_USE_VALUE_COUNTER ) - m_progr = sm_progr; - ++sm_progr; - wxLogTrace( cowTraceMask, wxT("(%s) Init a new object progr=%d"), - __PRETTY_FUNCTION__, m_progr ); -#endif - return data; -} - -//! \overload wxJSONValue() -wxJSONValue::wxJSONValue(wxJSONType type) { - m_refData = 0; - Init(type); -} - -//! \overload wxJSONValue() -wxJSONValue::wxJSONValue(int i) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_INT);wxJSON_ASSERT(data); - if (data != 0) { - // the 'VAL_INT' macro expands to 'm_valLong' or 'm_valInt64' depending - // on 64-bits integer support being enabled on not - data->m_value.VAL_INT = i; - } -} - -//! \overload wxJSONValue() -wxJSONValue::wxJSONValue(unsigned int ui) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_UINT);wxJSON_ASSERT(data); - if (data != 0) { - // the 'VAL_UINT' macro expands to 'm_valULong' or 'm_valUInt64' depending - // on 64-bits integer support being enabled on not - data->m_value.VAL_UINT = ui; - } -} - -//! \overload wxJSONValue() -wxJSONValue::wxJSONValue(short int i) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_INT);wxJSON_ASSERT(data); - if (data != 0) { - // the 'VAL_INT' macro expands to 'm_valLong' or 'm_valInt64' depending - // on 64-bits integer support being enabled on not - data->m_value.VAL_INT = i; - } -} - -//! \overload wxJSONValue() -wxJSONValue::wxJSONValue(unsigned short ui) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_UINT);wxJSON_ASSERT(data); - if (data != 0) { - // the 'VAL_UINT' macro expands to 'm_valULong' or 'm_valUInt64' depending - // on 64-bits integer support being enabled on not - data->m_value.VAL_UINT = ui; - } -} - -//! \overload wxJSONValue() -wxJSONValue::wxJSONValue(bool b) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_BOOL);wxJSON_ASSERT(data); - if (data != 0) { - data->m_value.m_valBool = b; - } -} - -//! \overload wxJSONValue() -wxJSONValue::wxJSONValue(double d) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_DOUBLE);wxJSON_ASSERT(data); - if (data != 0) { - data->m_value.m_valDouble = d; - } -} - -//! \overload wxJSONValue() -wxJSONValue::wxJSONValue(const wxChar *str) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_CSTRING);wxJSON_ASSERT(data); - if (data != 0) { -#if !defined( WXJSON_USE_CSTRING ) - data->m_type = wxJSONTYPE_STRING; - data->m_valString.assign(str); -#else - data->m_value.m_valCString = str; -#endif - } -} - -//! \overload wxJSONValue() -wxJSONValue::wxJSONValue(const wxString &str) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_STRING);wxJSON_ASSERT(data); - if (data != 0) { - data->m_valString.assign(str); - } -} - -//! \overload wxJSONValue() -wxJSONValue::wxJSONValue(long int l) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_INT);wxJSON_ASSERT(data); - if (data != 0) { - data->m_value.VAL_INT = l; - } -} - -//! \overload wxJSONValue() -wxJSONValue::wxJSONValue(unsigned long int ul) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_UINT);wxJSON_ASSERT(data); - if (data != 0) { - data->m_value.VAL_UINT = ul; - } -} - -//! Construct a JSON value object of type \e memory \e buffer -/*! - Note that this ctor makes a deep copy of \c buff so changes made - to the original buffer does not reflect to the buffer stored in this - JSON value. - */ -wxJSONValue::wxJSONValue(const wxMemoryBuffer &buff) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_MEMORYBUFF);wxJSON_ASSERT(data); - if (data != 0) { - data->m_memBuff = new wxMemoryBuffer(); - const void *ptr = buff.GetData(); - size_t buffLen = buff.GetDataLen(); - if (buffLen > 0) { - data->m_memBuff->AppendData(ptr, buffLen); - } - } -} - -//! Construct a JSON value object of type \e memory \e buffer -/*! - Note that this ctor makes a deep copy of \c buff so changes made - to the original buffer does not reflect to the buffer stored in this - JSON value. - */ -wxJSONValue::wxJSONValue(const void *buff, size_t len) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_MEMORYBUFF);wxJSON_ASSERT(data); - if (data != 0 && len > 0) { - data->m_memBuff = new wxMemoryBuffer(); - data->m_memBuff->AppendData(buff, len); - } -} - -//! Copy constructor -/*! - The function copies the content of \c other in this - object. - Note that the JSON value object is not really copied; - the function calls Ref() in order to increment - the reference count of the \c wxJSONRefData structure. - */ -wxJSONValue::wxJSONValue(const wxJSONValue &other) { - m_refData = 0; - Ref(other); - - // the progressive counter of the ctor is not copied from - // the other wxJSONValue object: only data is shared, the - // progressive counter is not shared because this object - // is a copy of 'other' and it has its own progressive -#if defined( WXJSON_USE_VALUE_COUNTER ) - m_progr = sm_progr; - ++sm_progr; - wxLogTrace( cowTraceMask, wxT("(%s) Copy ctor - progr=%d other progr=%d"), - __PRETTY_FUNCTION__, m_progr, other.m_progr ); -#endif -} - -//! Dtor - calls UnRef(). -wxJSONValue::~wxJSONValue() { - UnRef(); -} - -// functions for retreiving the value type: they are all 'const' - -//! Return the type of the value stored in the object. -/*! - This function is the only one that does not ASSERT that the - \c m_refData data member is not NULL. - In fact, if the JSON value object does not contain a pointer - to a wxJSONRefData structure, the function returns the - wxJSONTYPE_INVALID constant which represent an invalid JSON value object. - Also note that the pointer to the referenced data structure - should NEVER be NULL. - - \par Integer types - - Integers are stored internally in a \b signed/unsigned \b long \b int - or, on platforms that support 64-bits integers, in a - \b wx(U)Int64 data type. - When constructed, it is assigned a generic integer type that only - depends on the sign: wxJSON_(U)INT regardless the size of the - stored value. - - This function can be used to know the actual size requirement - of the stored value and how it can be retrieved. The value - returned by this function is: - - - for signed integers: - - \b wxJSONTYPE_SHORT if the value is between SHORT_MIN and SHORT_MAX - - \b wxJSONTYPE_LONG if the value is between LONG_MIN and LONG_MAX - and greater than SHORT_MAX and less than SHORT_MIN - - \b wxJSONTYPE_INT64 if the value is greater than LONG_MAX and - less than LONG_MIN - - - for unsigned integers: - - \b wxJSONTYPE_USHORT if the value is between 0 and USHORT_MAX - - \b wxJSONTYPE_ULONG if the value is between 0 and ULONG_MAX - and greater than USHORT_MAX - - \b wxJSONTYPE_UINT64 if the value is greater than ULONG_MAX - - Note that this function never returns the wxJSONTYPE_(U)INT constant - because the \b int data type may have the same width as SHORT or LONG - depending on the platform. - This does not mean that you cannot use \b int as the return value: if - you use \b wxWidgets to develop application in only one platform, you - can use \b int because you know the size of the data type. - Otherwise, if is preferable to always use \b long instead of \b int. - - Also note that the class defines the \c IsInt() memberfunction which - works fine regardless the actual width of the \b int data type. - This function returns TRUE if the stored value fits in a \b int data - type whatever its size is on the current platform (16 or 32-bits). - - \sa SetType IsInt - */ -wxJSONType -wxJSONValue::GetType() const { - wxJSONRefData *data = GetRefData(); - wxJSONType type = wxJSONTYPE_INVALID; - if (data) { - type = data->m_type; - - // for integers and unsigned ints check the storage requirements - // note that ints are stored as 'long' or as 'long long' - switch (type) { - case wxJSONTYPE_INT: - // check if the integer fits in a SHORT INT - if (data->m_value.VAL_INT >= SHORT_MIN && - data->m_value.VAL_INT <= SHORT_MAX) { - type = wxJSONTYPE_SHORT; - } - // check if the value fits in LONG INT - else if (data->m_value.VAL_INT >= LONG_MIN - && data->m_value.VAL_INT <= LONG_MAX) { - type = wxJSONTYPE_LONG; - } else { - type = wxJSONTYPE_INT64; - } - break; - - case wxJSONTYPE_UINT: - if (data->m_value.VAL_UINT <= USHORT_MAX) { - type = wxJSONTYPE_USHORT; - } else if (data->m_value.VAL_UINT <= ULONG_MAX) { - type = wxJSONTYPE_ULONG; - } else { - type = wxJSONTYPE_UINT64; - } - break; - - default: - break; - } - } - return type; -} - -//! Return TRUE if the type of the value is wxJSONTYPE_NULL. -bool -wxJSONValue::IsNull() const { - wxJSONType type = GetType(); - bool r = false; - if (type == wxJSONTYPE_NULL) { - r = true; - } - return r; -} - -//! Return TRUE if the value stored is valid -/*! - The function returns TRUE if the wxJSONValue object was correctly - initialized - that is it contains a valid value. - A JSON object is valid if its type is not equal to wxJSONTYPE_INVALID. - Please note that the default ctor of wxJSONValue constructs a \b valid - JSON object of type \b null. - To create an invalid object you have to use; - \code - wxJSONValue v( wxJSONTYPE_INVALID ); - \endcode - */ -bool -wxJSONValue::IsValid() const { - wxJSONType type = GetType(); - bool r = false; - if (type != wxJSONTYPE_INVALID) { - r = true; - } - return r; -} - -//! Return TRUE if the type of the value stored is integer. -/*! - This function returns TRUE if the stored value is of - type signed integer and the numeric value fits in a - \b int data type. - In other words, the function returns TRUE if the \c wxJSONRefData::m_type - data member is of type \c wxJSONTYPE_INT and: - - \code - INT_MIN <= m_value <= INT_MAX - \endcode - - Note that if you are developing cross-platform applications you should never - use \b int as the integer data type but \b long for 32-bits integers and - \b short for 16-bits integers. - This is because the \b int data type may have different width on different - platforms. - Regardless the widht of the data type (16 or 32 bits), the function returns - the correct result because it relies on the INT_MAX and INT_MIN macros. - - \sa \ref json_internals_integer - */ -bool -wxJSONValue::IsInt() const { - wxJSONType type = GetType(); - bool r = false; - // if the type is SHORT the value fits into an INT, too - if (type == wxJSONTYPE_SHORT) { - r = true; - } else if (type == wxJSONTYPE_LONG) { - // in case of LONG, check if the bit width is the same - if (INT_MAX == LONG_MAX) { - r = true; - } - } - return r; -} - -//! Return TRUE if the type of the value stored is 16-bit integer. -/*! - This function returns TRUE if the stored value is of - type signed integer and the numeric value fits in a - \b short \b int data type (16-bit integer). - In other words, the function returns TRUE if the \c wxJSONRefData::m_type - data member is of type \c wxJSONTYPE_INT and: - - \code - SHORT_MIN <= m_value <= SHORT_MAX - \endcode - - \sa \ref json_internals_integer - */ -bool -wxJSONValue::IsShort() const { - wxJSONType type = GetType(); - bool r = false; - if (type == wxJSONTYPE_SHORT) { - r = true; - } - return r; -} - -//! Return TRUE if the type of the value stored is a unsigned int. -/*! - This function returns TRUE if the stored value is of - type unsigned integer and the numeric value fits int a - \b int data type. - In other words, the function returns TRUE if the \c wxJSONRefData::m_type - data member is of type \c wxJSONTYPE_UINT and: - - \code - 0 <= m_value <= UINT_MAX - \endcode - - Note that if you are developing cross-platform applications you should never - use \b unsigned \b int as the integer data type but \b unsigned \b long for - 32-bits integers and \b unsigned \b short for 16-bits integers. - This is because the \b unsigned \b int data type may have different width - on different platforms. - Regardless the widht of the data type (16 or 32 bits), the function returns - the correct result because it relies on the UINT_MAX macro. - - \sa \ref json_internals_integer - */ -bool -wxJSONValue::IsUInt() const { - wxJSONType type = GetType(); - bool r = false; - if (type == wxJSONTYPE_USHORT) { - r = true; - } else if (type == wxJSONTYPE_ULONG) { - if (INT_MAX == LONG_MAX) { - r = true; - } - } - return r; -} - -//! Return TRUE if the type of the value stored is a unsigned short. -/*! - This function returns TRUE if the stored value is of - type unsigned integer and the numeric value fits in a - \b unsigned \b short \b int data type. - In other words, the function returns TRUE if the \c wxJSONRefData::m_type - data member is of type \c wxJSONTYPE_UINT and: - - \code - 0 <= m_value <= USHORT_MAX - \endcode - - \sa \ref json_internals_integer - */ -bool -wxJSONValue::IsUShort() const { - wxJSONType type = GetType(); - bool r = false; - if (type == wxJSONTYPE_USHORT) { - r = true; - } - return r; -} - -//! Return TRUE if the stored value is an integer which fits in a long int -/*! - This function returns TRUE if the stored value is of - type signed LONG integer and the numeric value fits int a - \b long \b int data type. - In other words, the function returns TRUE if the \c wxJSONRefData::m_type - data member is of type \c wxJSONTYPE_INT and: - - \code - LONG_MIN <= m_value <= LONG_MAX - \endcode - - \sa \ref json_internals_integer - */ -bool -wxJSONValue::IsLong() const { - wxJSONType type = GetType(); - bool r = false; - if (type == wxJSONTYPE_LONG || type == wxJSONTYPE_SHORT) { - r = true; - } - return r; -} - -//! Return TRUE if the stored value is an integer which fits in a unsigned long int -/*! - This function returns TRUE if the stored value is of - type unsigned LONG integer and the numeric value fits int a - \b unsigned \b long \b int data type. - In other words, the function returns TRUE if the \c wxJSONRefData::m_type - data member is of type \c wxJSONTYPE_UINT and: - - \code - 0 <= m_value <= ULONG_MAX - \endcode - - \sa \ref json_internals_integer - */ -bool -wxJSONValue::IsULong() const { - wxJSONType type = GetType(); - bool r = false; - if (type == wxJSONTYPE_ULONG || type == wxJSONTYPE_USHORT) { - r = true; - } - return r; -} - -//! Return TRUE if the type of the value stored is a boolean. -bool -wxJSONValue::IsBool() const { - wxJSONType type = GetType(); - bool r = false; - if (type == wxJSONTYPE_BOOL) { - r = true; - } - return r; -} - -//! Return TRUE if the type of the value stored is a double. -bool -wxJSONValue::IsDouble() const { - wxJSONType type = GetType(); - bool r = false; - if (type == wxJSONTYPE_DOUBLE) { - r = true; - } - return r; -} - -//! Return TRUE if the type of the value stored is a wxString object. -bool -wxJSONValue::IsString() const { - wxJSONType type = GetType(); - bool r = false; - if (type == wxJSONTYPE_STRING) { - r = true; - } - return r; -} - -//! Return TRUE if the type of the value stored is a pointer to a static C string. -/*! - This function returns TRUE if, and only if the stored value is a - pointer to a static C-string and the C-string storage is enabled in - the wxJSON library. - By default, C-string storage is not enabled in the library so this - function always returns FALSE. - To know more about C-strings read \ref json_internals_cstring - */ -bool -wxJSONValue::IsCString() const { - wxJSONType type = GetType(); - bool r = false; - if (type == wxJSONTYPE_CSTRING) { - r = true; - } - return r; -} - -//! Return TRUE if the type of the value stored is an array type. -bool -wxJSONValue::IsArray() const { - wxJSONType type = GetType(); - bool r = false; - if (type == wxJSONTYPE_ARRAY) { - r = true; - } - return r; -} - -//! Return TRUE if the type of this value is a key/value map. -bool -wxJSONValue::IsObject() const { - wxJSONType type = GetType(); - bool r = false; - if (type == wxJSONTYPE_OBJECT) { - r = true; - } - return r; -} - -//! Return TRUE if the type of this value is a binary memory buffer. -bool -wxJSONValue::IsMemoryBuff() const { - wxJSONType type = GetType(); - bool r = false; - if (type == wxJSONTYPE_MEMORYBUFF) { - r = true; - } - return r; -} - -// get the stored value; all these functions are 'const' - -//! Return the stored value as an integer. -/*! - The function returns the stored value as an integer. - Note that the function does not check that the type of the - value is actually an integer and it just returns the content - of the wxJSONValueHolder union. - However, in debug builds, the function ASSERTs that the - type of the stored value \c IsInt(). - - \sa \ref json_internals_integer - \sa \ref wxjson_tutorial_get - */ -int -wxJSONValue::AsInt() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - int i = (int) data->m_value.VAL_INT; - - wxJSON_ASSERT(IsInt()); - return i; -} - -//! Return the stored value as a boolean. -/*! - The function returns the stored value as a boolean. - Note that the function does not check that the type of the - value is actually a boolean and it just returns the content - of the wxJSONValueHolder union. - However, in debug builds, the function ASSERTs that the - type of the stored value is wxJSONTYPE_BOOL. - - \sa \ref wxjson_tutorial_get - */ -bool -wxJSONValue::AsBool() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data);wxJSON_ASSERT(data->m_type == wxJSONTYPE_BOOL); - return data->m_value.m_valBool; -} - -//! Return the stored value as a double. -/*! - The function returns the stored value as a double. - Note that the function does not check that the type of the - value is actually a double and it just returns the content - of the wxJSONValueHolder union as if it was a double. - However, in debug builds, the function ASSERTs that the - type of the stored value \c IsDouble(). - - \sa \ref wxjson_tutorial_get - */ -double -wxJSONValue::AsDouble() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - double d = data->m_value.m_valDouble;wxJSON_ASSERT(IsDouble()); - return d; -} - -//! Return the stored value as a wxWidget's string. -/*! - The function returns a string representation of the value - stored in the JSON object. - All value types are converted to a string by this function - and returned as a string: - - \li For integer the string is the string representation of - the numerical value in decimal notation; the function uses the - \b wxString::Printf() function for the conversion - - \li for doubles, the value is converted to a string using the - \b wxString::Printf("%.10g") function; the format string specifies - a precision of ten decimal digits and suppress trailing ZEROes - - \li for booleans the string returned is: \b true or \b false. - - \li if the value is a NULL value the \b null literal string is returned. - - \li if the value is of type wxJSONTYPE_INVALID, the literal string \b <invalid> - is returned. Note that this is NOT a valid JSON text. - - \li if the value is of type wxJSONTYPE_MEMORYBUFF the string returned contains the - hexadecimal digits of the first 5 bytes preceeded by the length of the buffer, - enclosed in parenthesis - - If the value is an array or map, the returned string is the number of - elements is the array/object enclosed in the JSON special characters that - identifies the array/object. Example: - - \code - [0] // an empty array - {12} // an object of 12 elements - \endcode - - \sa \ref wxjson_tutorial_get - */ -wxString -wxJSONValue::AsString() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - wxString s; - int size = Size(); - switch (data->m_type) { - case wxJSONTYPE_STRING: - s.assign(data->m_valString); - break; - case wxJSONTYPE_CSTRING: - s.assign(data->m_value.m_valCString); - break; - case wxJSONTYPE_INT: -#if defined( wxJSON_64BIT_INT ) - s.Printf(wxT("%") wxT(wxLongLongFmtSpec) wxT("i"), - data->m_value.m_valInt64); -#else - s.Printf( wxT("%ld"), data->m_value.m_valLong ); -#endif - break; - case wxJSONTYPE_UINT: -#if defined( wxJSON_64BIT_INT ) - s.Printf(wxT("%") wxT(wxLongLongFmtSpec) wxT("u"), - data->m_value.m_valUInt64); -#else - s.Printf( wxT("%lu"), data->m_value.m_valULong ); -#endif - break; - case wxJSONTYPE_DOUBLE: - s.Printf(wxT("%.10g"), data->m_value.m_valDouble); - break; - case wxJSONTYPE_BOOL: - s.assign((data->m_value.m_valBool ? - wxT("true") : wxT("false"))); - break; - case wxJSONTYPE_NULL: - s.assign(wxT("null")); - break; - case wxJSONTYPE_INVALID: - s.assign(wxT("")); - break; - case wxJSONTYPE_ARRAY: - s.Printf(wxT("[%d]"), size); - break; - case wxJSONTYPE_OBJECT: - s.Printf(wxT("{%d}"), size); - break; - case wxJSONTYPE_MEMORYBUFF: - s = MemoryBuffToString(*(data->m_memBuff), 5); - break; - default: - s.assign(wxT("wxJSONValue::AsString(): Unknown JSON type \'")); - s.append(TypeToString(data->m_type)); - s.append(wxT("\'")); - wxFAIL_MSG(s); - break; - } - return s; -} - -//! Return the stored value as a pointer to a static C string. -/*! - If the type of the value is stored as a C-string data type the - function just returns that pointer. - If the stored value is a wxString object, the function returns the - pointer returned by the \b wxString::c_str() function. - If the stored value is of all other JSON types, the functions returns a NULL pointer. - - Note that in versions prior to 0.5, the - function returned a NULL pointer also if the value is a \c wxString object. - - \sa \ref json_internals_cstring - \sa \ref wxjson_tutorial_get - - */ -const wxChar * -wxJSONValue::AsCString() const { - const wxChar *s = 0; - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - switch (data->m_type) { - case wxJSONTYPE_CSTRING: - s = data->m_value.m_valCString; - break; - case wxJSONTYPE_STRING: - s = data->m_valString.c_str(); - break; - default: - break; - } - return s; -} - -//! Return the stored value as a unsigned int. -/*! - The function returns the stored value as a unsigned integer. - Note that the function does not check that the type of the - value is actually a unsigned integer and it just returns the content - of the wxJSONValueHolder union. - However, in debug builds, the function ASSERTs that the - type of the stored value is wxJSONTYPE_UINT. - - \sa \ref json_internals_integer - \sa \ref wxjson_tutorial_get - */ -unsigned int -wxJSONValue::AsUInt() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - unsigned int ui = (unsigned) data->m_value.VAL_UINT; - - wxJSON_ASSERT(IsUInt()); - return ui; -} - -//! Returns the value as a long integer -/*! - The function returns the stored value as a long integer. - Note that the function does not check that the type of the - value is actually a long integer and it just returns the content - of the wxJSONValueHolder union. - However, in debug builds, the function ASSERTs that the - type of the stored value \c IsLong(). - - \sa \ref json_internals_integer - \sa \ref wxjson_tutorial_get - */ -long int -wxJSONValue::AsLong() const { - long int l; - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - l = (long) data->m_value.VAL_INT; - - wxJSON_ASSERT(IsLong()); - return l; -} - -//! Returns the value as a unsigned long integer -/*! - The function returns the stored value as a unsigned long integer. - Note that the function does not check that the type of the - value is actually a unsigned long integer and it just returns the content - of the wxJSONValueHolder union. - However, in debug builds, the function ASSERTs that the - type of the stored value \c IsLong(). - - \sa \ref json_internals_integer - \sa \ref wxjson_tutorial_get - */ -unsigned long int -wxJSONValue::AsULong() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - unsigned long int ul = (unsigned long) data->m_value.VAL_UINT; - - wxJSON_ASSERT(IsULong()); // expands only in debug builds - return ul; -} - -//! Returns the value as a short integer -/*! - The function returns the stored value as a short integer. - Note that the function does not check that the type of the - value is actually a short integer and it just returns the content - of the wxJSONValueHolder union. - However, in debug builds, the function ASSERTs that the - type of the stored value \c IsShort(). - - \sa \ref json_internals_integer - \sa \ref wxjson_tutorial_get - */ -short int -wxJSONValue::AsShort() const { - short int i; - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - i = (short) data->m_value.VAL_INT; - - wxJSON_ASSERT(IsShort()); - return i; -} - -//! Returns the value as a unsigned short integer -/*! - The function returns the stored value as a unsigned short integer. - Note that the function does not check that the type of the - value is actually a unsigned short and it just returns the content - of the wxJSONValueHolder union. - However, in debug builds, the function ASSERTs that the - type of the stored value \c IsUShort(). - - \sa \ref json_internals_integer - \sa \ref wxjson_tutorial_get - */ -unsigned short -wxJSONValue::AsUShort() const { - unsigned short ui; - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - ui = (unsigned short) data->m_value.VAL_UINT; - - wxJSON_ASSERT(IsUShort()); - return ui; -} - -//! Stores the value of this object in the provided argument -/*! - The functions of the form \c AsXxxxxx(T&) are the same as the \c AsXxxxxxx() - but store the value in the provided argument and return TRUE if the value of - this object is of the correct type. - By using these functions you can get the value and test if the JSON value is - of the expected type in only one step. - For example: - \code - int i; wxJSONValue v(10); - if ( !v.AsInt( i )) { - cout << "Error: value is not of the expected type"; - } - \endcode - This is the same as: - \code - int i; wxJSONValue v(10); - if ( v.IsInt() { - i = v.AsInt(); - } - else { - cout << "Error: value is not of the expected type"; - } - \endcode - Thanks to \b catalin who has suggested this new feature. - */ -bool -wxJSONValue::AsInt(int &i) const { - bool r = false; - if (IsInt()) { - i = AsInt(); - r = true; - } - return r; -} - -bool -wxJSONValue::AsUInt(unsigned int &ui) const { - bool r = false; - if (IsUInt()) { - ui = AsUInt(); - r = true; - } - return r; -} - -bool -wxJSONValue::AsShort(short int &s) const { - bool r = false; - if (IsShort()) { - s = AsShort(); - r = true; - } - return r; -} - -bool -wxJSONValue::AsUShort(unsigned short &us) const { - bool r = false; - if (IsUShort()) { - us = AsUShort(); - r = true; - } - return r; -} - -bool -wxJSONValue::AsLong(long int &l) const { - bool r = false; - if (IsLong()) { - l = AsLong(); - r = true; - } - return r; -} - -bool -wxJSONValue::AsULong(unsigned long &ul) const { - bool r = false; - if (IsULong()) { - ul = AsULong(); - r = true; - } - return r; -} - -bool -wxJSONValue::AsBool(bool &b) const { - bool r = false; - if (IsBool()) { - b = AsBool(); - r = true; - } - return r; -} - -bool -wxJSONValue::AsDouble(double &d) const { - bool r = false; - if (IsDouble()) { - d = AsDouble(); - r = true; - } - return r; -} - -//! Return this string value in the provided argument -/*! - This function is different from \c AsString because the latter always returns - a string also when this object does not contain a string. In that case, a string - representation of this value is returned. - This function, instead, returns TRUE only if this object contains a string, that is - only if \c IsString() returns TRUE. - Also note that the string value is only stored in \c str if this object actually - contains a \b string or \b c-string value. - \c str will never contain a string representation of other types. - */ -bool -wxJSONValue::AsString(wxString &str) const { - bool r = IsString(); - if (r) { - str = AsString(); - } - return r; -} - -bool -wxJSONValue::AsCString(wxChar *ch) const { - bool r = IsCString(); - if (r) { - ch = (wxChar *) AsCString(); - } - return r; -} - -//! Returns the value as a memory buffer -/*! - The function returns the \e memory \e buffer object stored in - this JSON object. - Note that as of wxWidgets 2.8 and 2.9 the \b wxMemoryBuffer object uses - reference counting when copying the actual buffer but the class itself - is not a \e copy-on-write structure so changes made to one buffer affects - all other copies made from it. - This means that if you make a change to the returned copy of the memory - buffer, the change affects also the memory buffer stored in this JSON value. - - If this JSON object does not contain a \e wxJSONTYPE_MEMORYBUFF type - the function returns an empty memory buffer object. - An empty memory buffer is also returned if this JSON - type contains a valid, empty memory buffer. - You have to use the IsMemoryBuff() function to known the type of the - JSON value contained in this object, or the overloaded version of - this function. - */ -wxMemoryBuffer -wxJSONValue::AsMemoryBuff() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - wxMemoryBuffer buff; - if (data->m_memBuff) { - buff = *(data->m_memBuff); - } - - wxJSON_ASSERT(IsMemoryBuff()); - return buff; -} - -//! Returns the value as a memory buffer -/*! - The function returns the \e memory \e buffer object stored in - this JSON object. - Note that as of wxWidgets 2.8 and 2.9 the \b wxMemoryBuffer object uses - reference counting when copying the actual buffer but the class itself - is not a \e copy-on-write structure so changes made to one buffer affects - all other copies made from it. - This means that if you make a change to the returned copy of the memory - buffer, the change affects also the memory buffer stored in this JSON value. - - If this JSON object does not contain a \e wxJSONTYPE_MEMORYBUFF type - the function returns an empty memory buffer object. - An empty memory buffer is also returned if this JSON - type contains a valid, empty memory buffer. - You have to use the IsMemoryBuff() function to known the type of the - JSON value contained in this object, or the overloaded version of - this function. - */ -bool -wxJSONValue::AsMemoryBuff(wxMemoryBuffer &buff) const { - bool r = IsMemoryBuff(); - if (r) { - buff = AsMemoryBuff(); - } - return r; -} - -// internal use - -//! Return the stored value as a map object. -/*! - This function is for testing and debugging purposes and you shold never use it. - To retreive values from an array or map JSON object use the \c Item() or ItemAt() - memberfunctions or the subscript operator. - If the stored value is not a map type, returns a NULL pointer. - */ -const wxJSONInternalMap * -wxJSONValueAsMap(const wxJSONValue &val) { - wxJSONRefData *data = val.GetRefData();wxJSON_ASSERT(data); - - const wxJSONInternalMap *v = 0; - if (data->m_type == wxJSONTYPE_OBJECT) { - v = &(data->m_valMap); - } - return v; -} - -//! Return the stored value as an array object. -/*! - This function is for testing and debugging purposes and you shold never use it. - To retreive values from an array or map JSON object use the \c Item() or ItemAt() - memberfunctions or the subscript operator. - If the stored value is not an array type, returns a NULL pointer. - */ -const wxJSONInternalArray * -wxJSONValueAsArray(const wxJSONValue &val) { - wxJSONRefData *data = val.GetRefData();wxJSON_ASSERT(data); - - const wxJSONInternalArray *v = 0; - if (data->m_type == wxJSONTYPE_ARRAY) { - v = &(data->m_valArray); - } - return v; -} - -// retrieve the members and other info - -//! Return TRUE if the object contains an element at the specified index. -/*! - If the stoerd value is not an array or a map, the function returns FALSE. - */ -bool -wxJSONValue::HasMember(unsigned index) const { - bool r = false; - int size = Size(); - if (index < (unsigned) size) { - r = true; - } - return r; -} - -//! Return TRUE if the object contains an element at the specified key. -/*! - If the stored value is not a key/map map, the function returns FALSE. - */ -bool -wxJSONValue::HasMember(const wxString &key) const { - bool r = false; - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - if (data && data->m_type == wxJSONTYPE_OBJECT) { - wxJSONInternalMap::iterator it = data->m_valMap.find(key); - if (it != data->m_valMap.end()) { - r = true; - } - } - return r; -} - -//! Return the size of the array or map stored in this value. -/*! - Note that both the array and the key/value map may have a size of - ZERO elements. - If the stored value is not an array nor a key/value hashmap, the - function returns -1. - */ -int -wxJSONValue::Size() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - int size = -1; - if (data->m_type == wxJSONTYPE_ARRAY) { - size = (int) data->m_valArray.GetCount(); - } - if (data->m_type == wxJSONTYPE_OBJECT) { - size = (int) data->m_valMap.size(); - } - return size; -} - -//! Return the array of keys of this JSON object. -/*! - If the stored value is a key/value map, the function returns an - array of strings containing the \e key of all elements. - Note that the returned array may be empty if the map has ZERO - elements. - An empty string array is also returned if the stored value is - not a key/value map. - Also note that in debug builds, the function wxJSON_ASSERTs that the - type of the stored object is wxJSONTYPE_OBJECT. - */ -wxArrayString -wxJSONValue::GetMemberNames() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data);wxJSON_ASSERT(data->m_type == wxJSONTYPE_OBJECT); - - wxArrayString arr; - if (data->m_type == wxJSONTYPE_OBJECT) { - wxJSONInternalMap::iterator it; - for (it = data->m_valMap.begin(); it != data->m_valMap.end(); it++) { - arr.Add(it->first); - } - } - return arr; -} - -// appending items, resizing and deleting items -// NOTE: these functions are not 'const' so we have to call -// the COW() function before accessing data - -//! Append the specified value in the array. -/*! - The function appends the value specified in the parameter to the array - contained in this object. - If this object does not contain an array type, the actual content is - deleted, a new array type is created and the JSON value \c value is - appended to the newly created array. - Returns a reference to the appended object. - */ -wxJSONValue & -wxJSONValue::Append(const wxJSONValue &value) { - wxJSONRefData *data = COW();wxJSON_ASSERT(data); - if (data->m_type != wxJSONTYPE_ARRAY) { - // we have to change the type of the actual object to the array type - SetType(wxJSONTYPE_ARRAY); - } - // we add the wxJSONValue object to the wxObjArray: note that the - // array makes a copy of the JSON-value object by calling its - // copy ctor thus using reference count - data->m_valArray.Add(value); - wxJSONValue &v = data->m_valArray.Last(); - return v; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(int i) { - wxJSONValue v(i); - wxJSONValue &r = Append(v); - return r; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(short int i) { - wxJSONValue v(i); - wxJSONValue &r = Append(v); - return r; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(long int l) { - wxJSONValue v(l); - wxJSONValue &r = Append(v); - return r; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(bool b) { - wxJSONValue v(b); - wxJSONValue &r = Append(v); - return r; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(unsigned int ui) { - wxJSONValue v(ui); - wxJSONValue &r = Append(v); - return r; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(unsigned short ui) { - wxJSONValue v(ui); - wxJSONValue &r = Append(v); - return r; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(unsigned long ul) { - wxJSONValue v(ul); - wxJSONValue &r = Append(v); - return r; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(double d) { - wxJSONValue v(d); - wxJSONValue &r = Append(v); - return r; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(const wxChar *str) { - wxJSONValue v(str); - wxJSONValue &r = Append(v); - return r; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(const wxString &str) { - wxJSONValue v(str); - wxJSONValue &r = Append(v); - return r; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(const wxMemoryBuffer &buff) { - wxJSONValue v(buff); - wxJSONValue &r = Append(v); - return r; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(const void *buff, size_t len) { - wxJSONValue v(buff, len); - wxJSONValue &r = Append(v); - return r; -} - -//! Concatenate a string to this string object. -/*! - The function concatenates \c str to the string contained - in this object and returns TRUE if the operation is succefull. - If the value stored in this value is not a string object - the function does nothing and returns FALSE. - Note that in order to be successfull, the value must contain - a \b wxString object and not a pointer to C-string. - */ -bool -wxJSONValue::Cat(const wxString &str) { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - bool r = false; - if (data->m_type == wxJSONTYPE_STRING) { - data = COW();wxJSON_ASSERT(data); - data->m_valString.append(str); - r = true; - } - return r; -} - -//! Concatenate a memory buffer to this memory buffer object. -/*! - The function concatenates \c buff to the \b wxMemoryBuffer object contained - in this object and returns TRUE if the operation is succefull. - If the value stored in this value is not a memory buffer object - the function does nothing and returns FALSE. - */ -bool -wxJSONValue::Cat(const wxMemoryBuffer &buff) { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - bool r = false; - if (data->m_type == wxJSONTYPE_MEMORYBUFF) { - data = COW();wxJSON_ASSERT(data); - data->m_memBuff->AppendData(buff.GetData(), buff.GetDataLen()); - r = true; - } - return r; -} - -//! \overload Cat( const wxString& ) -bool -wxJSONValue::Cat(const wxChar *str) { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - bool r = false; - if (data->m_type == wxJSONTYPE_STRING) { - data = COW();wxJSON_ASSERT(data); - data->m_valString.append(str); - r = true; - } - return r; -} - -//! Remove the item at the specified index or key. -/*! - The function removes the item at index \c index or at the specified - key in the array or map. - If this object does not contain an array (for a index parameter) or a map - (for a key parameter), the function does nothing and returns FALSE. - If the element does not exist, FALSE is returned. - */ -bool -wxJSONValue::Remove(int index) { - wxJSONRefData *data = COW();wxJSON_ASSERT(data); - - bool r = false; - if (data->m_type == wxJSONTYPE_ARRAY) { - data->m_valArray.RemoveAt(index); - r = true; - } - return r; -} - -//! \overload Remove( int ) -bool -wxJSONValue::Remove(const wxString &key) { - wxJSONRefData *data = COW();wxJSON_ASSERT(data); - - bool r = false; - if (data->m_type == wxJSONTYPE_OBJECT) { - wxJSONInternalMap::size_type count = data->m_valMap.erase(key); - if (count > 0) { - r = true; - } - } - return r; -} - -//! Clear the object value. -/*! - This function causes the object to be empty. - The function simply calls UnRef() making this object to become - invalid and set its type to wxJSONTYPE_INVALID. - */ -void -wxJSONValue::Clear() { - UnRef(); - SetType(wxJSONTYPE_INVALID); -} - -// retrieve an item - -//! Return the item at the specified index. -/*! - The function returns a reference to the object at the specified - index. - If the element does not exist, the array is enlarged to \c index + 1 - elements and a reference to the last element will be returned. - New elements will contain NULL values. - If this object does not contain an array, the old value is - replaced by an array object which will be enlarged to the needed - dimension. - */ -wxJSONValue & -wxJSONValue::Item(unsigned index) { - wxJSONRefData *data = COW();wxJSON_ASSERT(data); - - if (data->m_type != wxJSONTYPE_ARRAY) { - data = SetType(wxJSONTYPE_ARRAY); - } - int size = Size();wxJSON_ASSERT(size >= 0); - // if the desired element does not yet exist, we create as many - // elements as needed; the new values will be 'null' values - if (index >= (unsigned) size) { - wxJSONValue v(wxJSONTYPE_NULL); - int missing = index - size + 1; - data->m_valArray.Add(v, missing); - } - return data->m_valArray.Item(index); -} - -//! Return the item at the specified key. -/*! - The function returns a reference to the object in the map - that has the specified key. - If \c key does not exist, a new NULL value is created with - the provided key and a reference to it is returned. - If this object does not contain a map, the old value is - replaced by a map object. - */ -wxJSONValue & -wxJSONValue::Item(const wxString &key) { - wxLogTrace(traceMask, wxT("(%s) searched key=\'%s\'"), __PRETTY_FUNCTION__, key.c_str()); - wxLogTrace(traceMask, wxT("(%s) actual object: %s"), __PRETTY_FUNCTION__, GetInfo().c_str()); - - wxJSONRefData *data = COW();wxJSON_ASSERT(data); - - if (data->m_type != wxJSONTYPE_OBJECT) { - // deletes the contained value; - data = SetType(wxJSONTYPE_OBJECT); - return data->m_valMap[key]; - } - wxLogTrace(traceMask, wxT("(%s) searching key \'%s' in the actual object"), - __PRETTY_FUNCTION__, key.c_str()); - return data->m_valMap[key]; -} - -//! Return the item at the specified index. -/*! - The function returns a copy of the object at the specified - index. - If the element does not exist, the function returns an \b invalid value. - */ -wxJSONValue -wxJSONValue::ItemAt(unsigned index) const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - wxJSONValue v(wxJSONTYPE_INVALID); - if (data->m_type == wxJSONTYPE_ARRAY) { - int size = Size();wxJSON_ASSERT(size >= 0); - if (index < (unsigned) size) { - v = data->m_valArray.Item(index); - } - } - return v; -} - -//! Return the item at the specified key. -/*! - The function returns a copy of the object in the map - that has the specified key. - If \c key does not exist, an \b invalid value is returned. - */ -wxJSONValue -wxJSONValue::ItemAt(const wxString &key) const { - wxLogTrace(traceMask, wxT("(%s) searched key=\'%s\'"), __PRETTY_FUNCTION__, key.c_str()); - wxLogTrace(traceMask, wxT("(%s) actual object: %s"), __PRETTY_FUNCTION__, GetInfo().c_str()); - - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - wxJSONValue v(wxJSONTYPE_INVALID); - if (data->m_type == wxJSONTYPE_OBJECT) { - wxJSONInternalMap::const_iterator it = data->m_valMap.find(key); - if (it != data->m_valMap.end()) { - v = it->second; - } - } - return v; -} - -//! Return the item at the specified index. -/*! - The function returns a reference to the object at the specified - index. - If the element does not exist, the array is enlarged to \c index + 1 - elements and a reference to the last element will be returned. - New elements will contain NULL values. - If this object does not contain an array, the old value is - replaced by an array object. - */ -wxJSONValue & -wxJSONValue::operator[](unsigned index) { - wxJSONValue &v = Item(index); - return v; -} - -//! Return the item at the specified key. -/*! - The function returns a reference to the object in the map - that has the specified key. - If \c key does not exist, a new NULL value is created with - the provided key and a reference to it is returned. - If this object does not contain a map, the old value is - replaced by a map object. - */ -wxJSONValue & -wxJSONValue::operator[](const wxString &key) { - wxJSONValue &v = Item(key); - return v; -} - -// -// assignment operators -// note that reference counting is only used if the original -// value is a wxJSONValue object -// in all other cases, the operator= function deletes the old -// content and assigns the new one - -//! Assign the specified value to this object replacing the old value. -/*! - The assignment operator assigns to this object the value specified in the - right operand of the assignment operator. - Note that the old value is deleted but not the other data members - in the wxJSONRefData structure. - This is particularly usefull for the parser class which stores - comment lines in a temporary wxJSONvalue object that is of type - wxJSONTYPE_INVALID. - As comment lines may apear before the value they refer to, comments - are stored in a value that is not yet being read. - when the value is read, it is assigned to the temporary JSON value - object without deleting the comment lines. - */ -wxJSONValue & -wxJSONValue::operator=(int i) { - wxJSONRefData *data = SetType(wxJSONTYPE_INT); - data->m_value.VAL_INT = i; - return *this; -} - -//! \overload operator = (int) -wxJSONValue & -wxJSONValue::operator=(bool b) { - wxJSONRefData *data = SetType(wxJSONTYPE_BOOL); - data->m_value.m_valBool = b; - return *this; -} - -//! \overload operator = (int) -wxJSONValue & -wxJSONValue::operator=(unsigned int ui) { - wxJSONRefData *data = SetType(wxJSONTYPE_UINT); - data->m_value.VAL_UINT = ui; - return *this; -} - -//! \overload operator = (int) -wxJSONValue & -wxJSONValue::operator=(long l) { - wxJSONRefData *data = SetType(wxJSONTYPE_INT); - data->m_value.VAL_INT = l; - return *this; -} - -//! \overload operator = (int) -wxJSONValue & -wxJSONValue::operator=(unsigned long ul) { - wxJSONRefData *data = SetType(wxJSONTYPE_UINT); - data->m_value.VAL_UINT = ul; - return *this; -} - -//! \overload operator = (int) -wxJSONValue & -wxJSONValue::operator=(short i) { - wxJSONRefData *data = SetType(wxJSONTYPE_INT); - data->m_value.VAL_INT = i; - return *this; -} - -//! \overload operator = (int) -wxJSONValue & -wxJSONValue::operator=(unsigned short ui) { - wxJSONRefData *data = SetType(wxJSONTYPE_UINT); - data->m_value.VAL_UINT = ui; - return *this; -} - -//! \overload operator = (int) -wxJSONValue & -wxJSONValue::operator=(double d) { - wxJSONRefData *data = SetType(wxJSONTYPE_DOUBLE); - data->m_value.m_valDouble = d; - return *this; -} - -//! \overload operator = (int) -wxJSONValue & -wxJSONValue::operator=(const wxChar *str) { - wxJSONRefData *data = SetType(wxJSONTYPE_CSTRING); - data->m_value.m_valCString = str; -#if !defined( WXJSON_USE_CSTRING ) - data->m_type = wxJSONTYPE_STRING; - data->m_valString.assign(str); -#endif - return *this; -} - -//! \overload operator = (int) -wxJSONValue & -wxJSONValue::operator=(const wxString &str) { - wxJSONRefData *data = SetType(wxJSONTYPE_STRING); - data->m_valString.assign(str); - return *this; -} - -//! Assigns to this object a memory buffer type -/*! - As with the ctor, this function makes a deep copy of the - memory buffer \c buff so changes made to the original buffer - does not reflect to the memory buffer stored in this JSON value. - */ -wxJSONValue & -wxJSONValue::operator=(const wxMemoryBuffer &buff) { - wxJSONRefData *data = SetType(wxJSONTYPE_MEMORYBUFF); - data->m_memBuff = new wxMemoryBuffer(); - const void *ptr = buff.GetData(); - size_t len = buff.GetDataLen(); - if (data->m_memBuff && len) { - data->m_memBuff->AppendData(ptr, len); - } - return *this; -} - -//! Assignment operator using reference counting. -/*! - Unlike all other assignment operators, this one makes a - swallow copy of the other JSON value object. - The function calls \c Ref() to get a shared referenced - data. - \sa \ref json_internals_cow - */ -wxJSONValue & -wxJSONValue::operator=(const wxJSONValue &other) { - Ref(other); - return *this; -} - -// finding elements - -//! Return a value or a default value. -/*! - This function returns a copy of the value object for the specified key. - If the key is not found, a copy of \c defaultValue is returned. - Note that the returned values are not real copy of the \c key or the - default values because \e copy-on-write is used by this class. - However, you have to treat them as real copies; in other words, if you - change the values of the returned object your changes does not reflect - in the otiginal value. - Example: - \code - wxJSONValue defaultValue( 0 ); - wxJSONvalue v1; - v1["key"] = 100; // 'v1["key"]' contains the integer 100 - - // 'v2' contains 100 but it is a swallow copy of 'v1["key"]' - wxJSONValue v2 = v1.Get( "key", defaultValue ); - - // 'v1["key"]' still contains 100 - v2 = 200; - - // if you want your change to be reflected in the 'v1' object - // you have to assign it - v1["key"] = v2; - \endcode - */ -wxJSONValue -wxJSONValue::Get(const wxString &key, const wxJSONValue &defaultValue) const { - // NOTE: this function does many wxJSONValue copies. - // so implementing COW is a good thing - - // this is the first copy (the default value) - wxJSONValue v(defaultValue); - - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - if (data->m_type == wxJSONTYPE_OBJECT) { - wxJSONInternalMap::iterator it = data->m_valMap.find(key); - if (it != data->m_valMap.end()) { - v = it->second; - } - } - return v; -} - -// protected functions - -//! Find an element -/*! - The function returns a pointer to the element at index \c index - or a NULL pointer if \c index does not exist. - A NULL pointer is also returned if the object does not contain an - array nor a key/value map. - */ -wxJSONValue * -wxJSONValue::Find(unsigned index) const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - wxJSONValue *vp = 0; - - if (data->m_type == wxJSONTYPE_ARRAY) { - size_t size = data->m_valArray.GetCount(); - if (index < size) { - vp = &(data->m_valArray.Item(index)); - } - } - return vp; -} - -//! Find an element -/*! - The function returns a pointer to the element with key \c key - or a NULL pointer if \c key does not exist. - A NULL pointer is also returned if the object does not contain a - key/value map. - */ -wxJSONValue * -wxJSONValue::Find(const wxString &key) const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - wxJSONValue *vp = 0; - - if (data->m_type == wxJSONTYPE_OBJECT) { - wxJSONInternalMap::iterator it = data->m_valMap.find(key); - if (it != data->m_valMap.end()) { - vp = &(it->second); - } - } - return vp; -} - -//! Return a string description of the type -/*! - This static function is only usefull for debugging purposes and - should not be used by users of this class. - It simply returns a string representation of the JSON value - type stored in a object. - For example, if \c type is wxJSONTYPE_INT the function returns the - string "wxJSONTYPE_INT". - If \c type is out of range, an empty string is returned (should - never happen). - */ -wxString -wxJSONValue::TypeToString(wxJSONType type) { - static const wxChar *str[] = { - wxT("wxJSONTYPE_INVALID"), // 0 - wxT("wxJSONTYPE_NULL"), // 1 - wxT("wxJSONTYPE_INT"), // 2 - wxT("wxJSONTYPE_UINT"), // 3 - wxT("wxJSONTYPE_DOUBLE"), // 4 - wxT("wxJSONTYPE_STRING"), // 5 - wxT("wxJSONTYPE_CSTRING"), // 6 - wxT("wxJSONTYPE_BOOL"), // 7 - wxT("wxJSONTYPE_ARRAY"), // 8 - wxT("wxJSONTYPE_OBJECT"), // 9 - wxT("wxJSONTYPE_LONG"), // 10 - wxT("wxJSONTYPE_INT64"), // 11 - wxT("wxJSONTYPE_ULONG"), // 12 - wxT("wxJSONTYPE_UINT64"), // 13 - wxT("wxJSONTYPE_SHORT"), // 14 - wxT("wxJSONTYPE_USHORT"), // 15 - wxT("wxJSONTYPE_MEMORYBUFF"), // 16 - }; - - wxString s; - int idx = (int) type; - if (idx >= 0 && idx < 17) { - s = str[idx]; - } - return s; -} - -//! Returns informations about the object -/*! - The function is only usefull for debugging purposes and will probably - be dropped in future versions. - Returns a string that contains info about the object such as: - - \li the type of the object - \li the size - \li the progressive counter - \li the pointer to referenced data - \li the progressive counter of referenced data - \li the number of share of referenced data - - The \c deep parameter is used to specify if the function will be called - recursively in order to dump sub-items. If the parameter is TRUE than a - deep dump is executed. - - The \c indent is the initial indentation: it is incremented by 3 every - time the Dump() function is called recursively. - */ -wxString -wxJSONValue::Dump(bool deep, int indent) const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - wxJSONType type = GetType(); - - wxString s; - if (indent > 0) { - s.append(indent, ' '); - } - - wxString s1; - wxString s2; -#if defined( WXJSON_USE_VALUE_COUNTER ) - s1.Printf( wxT("Object: Progr=%d Type=%s Size=%d comments=%d\n"), - m_progr, - TypeToString( type ).c_str(), - Size(), - data->m_comments.GetCount() ); - s2.Printf(wxT(" : RefData=%p Progr=%d Num shares=%d\n"), - data, data->m_progr, data->GetRefCount() ); -#else - s1.Printf(wxT("Object: Type=%s Size=%d comments=%d\n"), - TypeToString(type).c_str(), - Size(), - data->m_comments.GetCount()); - s2.Printf(wxT(" : RefData=%p Num shares=%d\n"), - data, data->GetRefCount()); -#endif - s.append(s1); - if (indent > 0) { - s.append(indent, ' '); - } - s.append(s2); - - wxString sub; - - // if we have to do a deep dump, we call the Dump() function for - // every sub-item - if (deep) { - indent += 3; - const wxJSONInternalMap *map; - int size;; - wxJSONInternalMap::const_iterator it; - switch (type) { - case wxJSONTYPE_OBJECT: - map = wxJSONValueAsMap(*this); - size = Size(); - for (it = map->begin(); it != map->end(); ++it) { - const wxJSONValue &v = it->second; - sub = v.Dump(true, indent); - s.append(sub); - } - break; - case wxJSONTYPE_ARRAY: - size = Size(); - for (int i = 0; i < size; i++) { - const wxJSONValue *v = Find(i);wxJSON_ASSERT(v); - sub = v->Dump(true, indent); - s.append(sub); - } - break; - default: - break; - } - } - return s; -} - -//! Returns informations about the object -/*! - The function is only usefull for debugging purposes and will probably - be dropped in future versions. - You should not rely on this function to exist in future versions. - */ -wxString -wxJSONValue::GetInfo() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - wxString s; -#if defined( WXJSON_USE_VALUE_CONTER ) - s.Printf( wxT("Object: Progr=%d Type=%s Size=%d comments=%d\n"), - data->m_progr, - wxJSONValue::TypeToString( data->m_type ).c_str(), - Size(), - data->m_comments.GetCount() ); -#else - s.Printf(wxT("Object: Type=%s Size=%d comments=%d\n"), - (const char *) wxJSONValue::TypeToString(data->m_type).c_str(), - (int) Size(), (int) data->m_comments.GetCount()); -#endif - if (data->m_type == wxJSONTYPE_OBJECT) { - wxArrayString arr = GetMemberNames(); - for (unsigned int i = 0; i < arr.size(); i++) { - s.append(wxT(" Member name: ")); - s.append(arr[i]); - s.append(wxT("\n")); - } - } - return s; -} - -//! The comparison function -/*! - This function returns TRUE if this object looks like \c other. - Note that this class does not define a comparison operator - (the classical \b operator== function) because the notion - of \b equal for JSON values objects is not applicable. - The comment strings array are not compared: JSON value objects - are \b the \b same if they contains the same values, regardless the - comment's strings. - - Note that the function does not return the element that cause the - comparison to return FALSE. There is not a good structure to - tell this information. - If you need it for debugging purposes, you have to turn on the - \b sameas tracing feature by setting the WXTRACE environment - variable (you need a debug version of the application): - - \code - export WXTRACE=sameas // for unix systems that use bash - \endcode - - Note that if the two JSON value objects share the same referenced - data, the function immediatly returns TRUE without doing a deep - comparison which is, sure, useless. - For further info see \ref json_internals_compare. - */ -bool -wxJSONValue::IsSameAs(const wxJSONValue &other) const { - // this is a recursive function: it calls itself - // for every 'value' object in an array or map - bool r = false; - - // some variables used in the switch statement - int size; - wxJSONInternalMap::const_iterator it; - - // get the referenced data for the two objects - wxJSONRefData *data = GetRefData(); - wxJSONRefData *otherData = other.GetRefData(); - - if (data == otherData) { - wxLogTrace(compareTraceMask, wxT("(%s) objects share the same referenced data - r=TRUE"), - __PRETTY_FUNCTION__); - return true; - } - - // if the type does not match the function compares the values if - // they are of compatible types such as INT, UINT and DOUBLE - if (data->m_type != otherData->m_type) { - // if the types are not compatible, returns false - // otherwise compares the compatible types: INT, UINT and DOUBLE - double val; - switch (data->m_type) { - case wxJSONTYPE_INT: - if (otherData->m_type == wxJSONTYPE_UINT) { - // compare the bits and returns true if value is between 0 and LLONG_MAX - if ((data->m_value.VAL_UINT <= LLONG_MAX) && - (data->m_value.VAL_UINT == otherData->m_value.VAL_UINT)) { - r = true; - } - } else if (otherData->m_type == wxJSONTYPE_DOUBLE) { - val = data->m_value.VAL_INT; - if (val == otherData->m_value.m_valDouble) { - r = true; - } - } else { - r = false; - } - break; - case wxJSONTYPE_UINT: - if (otherData->m_type == wxJSONTYPE_INT) { - // compare the bits and returns true if value is between 0 and LLONG_MAX - if ((data->m_value.VAL_UINT <= LLONG_MAX) && - (data->m_value.VAL_UINT == otherData->m_value.VAL_UINT)) { - r = true; - } - } else if (otherData->m_type == wxJSONTYPE_DOUBLE) { - val = data->m_value.VAL_UINT; - if (val == otherData->m_value.m_valDouble) { - r = true; - } - } else { - r = false; - } - break; - case wxJSONTYPE_DOUBLE: - if (otherData->m_type == wxJSONTYPE_INT) { - val = otherData->m_value.VAL_INT; - if (val == data->m_value.m_valDouble) { - r = true; - } - } else if (otherData->m_type == wxJSONTYPE_UINT) { - val = otherData->m_value.VAL_UINT; - if (val == data->m_value.m_valDouble) { - r = true; - } - } else { - r = false; - } - break; - default: - r = false; - break; - } - return r; - } - - // the two objects have the same 'm_type' - - // for comparing wxJSONTYPE_CSTRING we use two temporary wxString - // objects: this is to avoid using strcmp() and wcscmp() which - // may not be available on all platforms - wxString s1, s2; - r = true; - int r1; - - switch (data->m_type) { - case wxJSONTYPE_INVALID: - case wxJSONTYPE_NULL: - // there is no need to compare the values - break; - case wxJSONTYPE_INT: - if (data->m_value.VAL_INT != otherData->m_value.VAL_INT) { - r = false; - } - break; - case wxJSONTYPE_UINT: - if (data->m_value.VAL_UINT != otherData->m_value.VAL_UINT) { - r = false; - } - break; - case wxJSONTYPE_DOUBLE: - if (data->m_value.m_valDouble != otherData->m_value.m_valDouble) { - r = false; - } - break; - case wxJSONTYPE_CSTRING: - s1 = wxString(data->m_value.m_valCString); - s2 = wxString(otherData->m_value.m_valCString); - if (s1 != s2) { - r = false; - } - break; - case wxJSONTYPE_BOOL: - if (data->m_value.m_valBool != otherData->m_value.m_valBool) { - r = false; - } - break; - case wxJSONTYPE_STRING: - if (data->m_valString != otherData->m_valString) { - r = false; - } - break; - case wxJSONTYPE_MEMORYBUFF: - // we cannot simply use the operator ==; we need a deep comparison - r1 = CompareMemoryBuff(*(data->m_memBuff), *(otherData->m_memBuff)); - if (r1 != 0) { - r = false; - } - break; - case wxJSONTYPE_ARRAY: - size = Size(); - wxLogTrace(compareTraceMask, wxT("(%s) Comparing an array object - size=%d"), - __PRETTY_FUNCTION__, size); - - if (size != other.Size()) { - wxLogTrace(compareTraceMask, wxT("(%s) Sizes does not match"), - __PRETTY_FUNCTION__); - return false; - } - // compares every element in this object with the element of - // the same index in the 'other' object - for (int i = 0; i < size; i++) { - wxLogTrace(compareTraceMask, wxT("(%s) Comparing array element=%d"), - __PRETTY_FUNCTION__, i); - wxJSONValue v1 = ItemAt(i); - wxJSONValue v2 = other.ItemAt(i); - - if (!v1.IsSameAs(v2)) { - return false; - } - } - break; - case wxJSONTYPE_OBJECT: - size = Size(); - wxLogTrace(compareTraceMask, wxT("(%s) Comparing a map obejct - size=%d"), - __PRETTY_FUNCTION__, size); - - if (size != other.Size()) { - wxLogTrace(compareTraceMask, wxT("(%s) Comparison failed - sizes does not match"), - __PRETTY_FUNCTION__); - return false; - } - // for every key calls itself on the value found in - // the other object. if 'key' does no exist, returns FALSE - for (it = data->m_valMap.begin(); it != data->m_valMap.end(); it++) { - wxString key = it->first; - wxLogTrace(compareTraceMask, wxT("(%s) Comparing map object - key=%s"), - __PRETTY_FUNCTION__, key.c_str()); - wxJSONValue otherVal = other.ItemAt(key); - bool isSame = it->second.IsSameAs(otherVal); - if (!isSame) { - wxLogTrace(compareTraceMask, wxT("(%s) Comparison failed for the last object"), - __PRETTY_FUNCTION__); - return false; - } - } - break; - default: - // should never happen - wxFAIL_MSG(wxT("wxJSONValue::IsSameAs() unexpected wxJSONType")); - break; - } - return r; -} - -//! Add a comment to this JSON value object. -/*! - The function adds a comment string to this JSON value object and returns - the total number of comment strings belonging to this value. - Note that the comment string must be a valid C/C++ comment because the - wxJSONWriter does not modify it. - In other words, a C++ comment string must start with '//' and must end with - a new-line character. If the final LF char is missing, the - automatically adds it. - You can also add C-style comments which must be enclosed in the usual - C-comment characters. - For C-style comments, the function does not try to append the final comment - characters but allows trailing whitespaces and new-line chars. - The \c position parameter is one of: - - \li wxJSONVALUE_COMMENT_BEFORE: the comment will be written before the value - \li wxJSONVALUE_COMMENT_INLINE: the comment will be written on the same line - \li wxJSONVALUE_COMMENT_AFTER: the comment will be written after the value - \li wxJSONVALUE_COMMENT_DEFAULT: the old value of comment's position is not - changed; if no comments were added to the value object this is the - same as wxJSONVALUE_COMMENT_BEFORE. - - To know more about comment's storage see \ref json_comment_add - - */ -int -wxJSONValue::AddComment(const wxString &str, int position) { - wxJSONRefData *data = COW();wxJSON_ASSERT(data); - - wxLogTrace(traceMask, wxT("(%s) comment=%s"), __PRETTY_FUNCTION__, str.c_str()); - int r = -1; - int len = str.length(); - if (len < 2) { - wxLogTrace(traceMask, wxT(" error: len < 2")); - return -1; - } - if (str[0] != '/') { - wxLogTrace(traceMask, wxT(" error: does not start with\'/\'")); - return -1; - } - if (str[1] == '/') { // a C++ comment: check that it ends with '\n' - wxLogTrace(traceMask, wxT(" C++ comment")); - if (str.GetChar(len - 1) != '\n') { - wxString temp(str); - temp.append(1, '\n'); - data->m_comments.Add(temp); - wxLogTrace(traceMask, wxT(" C++ comment: LF added")); - } else { - data->m_comments.Add(str); - } - r = data->m_comments.size(); - } else if (str[1] == '*') { // a C-style comment: check that it ends with '*/' - wxLogTrace(traceMask, wxT(" C-style comment")); - int lastPos = len - 1; - wxChar ch = str.GetChar(lastPos); - // skip leading whitespaces - while (ch == ' ' || ch == '\n' || ch == '\t') { - --lastPos; - ch = str.GetChar(lastPos); - } - if (str.GetChar(lastPos) == '/' && str.GetChar(lastPos - 1) == '*') { - data->m_comments.Add(str); - r = data->m_comments.size(); - } - } else { - wxLogTrace(traceMask, wxT(" error: is not a valid comment string")); - r = -1; - } - // if the comment was stored, store the position - if (r >= 0 && position != wxJSONVALUE_COMMENT_DEFAULT) { - data->m_commentPos = position; - } - return r; -} - -//! Add one or more comments to this JSON value object. -/*! - The function adds the strings contained in \c comments to the comment's - string array of this value object by calling the AddComment( const wxString&,int) - function for every string in the \c comment array. - Returns the number of strings correctly added. - */ -int -wxJSONValue::AddComment(const wxArrayString &comments, int position) { - int siz = comments.GetCount(); - int r = 0; - for (int i = 0; i < siz; i++) { - int r2 = AddComment(comments[i], position); - if (r2 >= 0) { - ++r; - } - } - return r; -} - -//! Return a comment string. -/*! - The function returns the comment string at index \c idx. - If \c idx is out of range, an empty string is returned. - If \c idx is equal to -1, then the function returns a string - that contains all comment's strings stored in the array. - */ -wxString -wxJSONValue::GetComment(int idx) const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - wxString s; - int size = data->m_comments.GetCount(); - if (idx < 0) { - for (int i = 0; i < size; i++) { - s.append(data->m_comments[i]); - } - } else if (idx < size) { - s = data->m_comments[idx]; - } - return s; -} - -//! Return the number of comment strings. -int -wxJSONValue::GetCommentCount() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - int d = data->m_comments.GetCount(); - wxLogTrace(traceMask, wxT("(%s) comment count=%d"), __PRETTY_FUNCTION__, d); - return d; -} - -//! Return the comment position. -int -wxJSONValue::GetCommentPos() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - return data->m_commentPos; -} - -//! Get the comment string's array. -const wxArrayString & -wxJSONValue::GetCommentArray() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - - return data->m_comments; -} - -//! Clear all comment strings -void -wxJSONValue::ClearComments() { - wxJSONRefData *data = COW();wxJSON_ASSERT(data); - - data->m_comments.clear(); -} - -//! Set the type of the stored value. -/*! - The function sets the type of the stored value as specified in - the provided argument. - If the actual type is equal to \c type, nothing happens and this - JSON value object retains the original type and value. - If the type differs, however, the original type and value are - lost. - - The function just sets the type of the object and not the - value itself. - If the object does not have a data structure it is allocated - using the CreateRefData() function unless the type to be set - is wxJSONTYPE_INVALID. In this case and if a data structure is - not yet allocated, it is not allocated. - - If the object already contains a data structure it is not deleted - but the type is changed in the original data structure. - Complex values in the old structure are cleared. - The \c type argument can be one of the following: - - \li wxJSONTYPE_INVALID: an empty (not initialized) JSON value - \li wxJSONTYPE_NULL: a NULL value - \li wxJSONTYPE_INT: an integer value - \li wxJSONTYPE_UINT: an unsigned integer - \li wxJSONTYPE_DOUBLE: a double precision number - \li wxJSONTYPE_BOOL: a boolean - \li wxJSONTYPE_CSTRING: a C string - \li wxJSONTYPE_STRING: a wxString object - \li wxJSONTYPE_ARRAY: an array of wxJSONValue objects - \li wxJSONTYPE_OBJECT: a hashmap of key/value pairs where \e value is a wxJSONValue object - \li wxJSONTYPE_LONG: a 32-bits integer value - \li wxJSONTYPE_ULONG: an unsigned 32-bits integer - \li wxJSONTYPE_INT64: a 64-bits integer value - \li wxJSONTYPE_UINT64: an unsigned 64-bits integer - \li wxJSONTYPE_SHORT: a signed short integer - \li wxJSONTYPE_USHORT: an unsigned short integer - \li wxJSONTYPE_MEMORYBUFF: a binary memory buffer - - The integer storage depends on the platform: for platforms that support 64-bits - integers, integers are always stored as 64-bits integers. - On platforms that do not support 64-bits integers, ints are stored as \b long \b int. - To know more about the internal representation of integers, read - \ref json_internals_integer. - - Note that there is no need to set a type for the object in order to assign - a value to it. - In other words, if you want to construct a JSON value which holds an integer - value of 10, just use the specific constructor: - \code - wxJSONValue value( 10 ); - \endcode - which sets the integer type and also the numeric value. - Moreover, there is no need to set the type for none of the handled types, - not only for primitive types but for complex types, too. - For example, if you want to construct an array of JSON values, just use - the default ctor and call the Append() member function which will append the - first element to the array and will set the array type: - \code - wxJSONValue value; - value.Append( "a string" ); - \endcode - \sa GetType - */ -wxJSONRefData * -wxJSONValue::SetType(wxJSONType type) { - wxJSONRefData *data = GetRefData(); - wxJSONType oldType = GetType(); - - // check that type is within the allowed range - wxJSON_ASSERT((type >= wxJSONTYPE_INVALID) && (type <= wxJSONTYPE_MEMORYBUFF)); - if ((type < wxJSONTYPE_INVALID) || (type > wxJSONTYPE_MEMORYBUFF)) { - type = wxJSONTYPE_INVALID; - } - - // the function unshares the referenced data but does not delete the - // structure. This is because the wxJSON reader stores comments - // that apear before the value in a temporary value of type wxJSONTYPE_INVALID - // which is invalid and, next, it stores the JSON value in the same - // wxJSONValue object. - // If we would delete the structure using 'Unref()' we loose the - // comments - data = COW(); - - // do nothing if the actual type is the same as 'type' - if (type == oldType) { - return data; - } - - // change the type of the referened structure - // NOTE: integer types are always stored as the generic integer types - if (type == wxJSONTYPE_LONG || type == wxJSONTYPE_INT64 || type == wxJSONTYPE_SHORT) { - type = wxJSONTYPE_INT; - } - if (type == wxJSONTYPE_ULONG || type == wxJSONTYPE_UINT64 || type == wxJSONTYPE_USHORT) { - type = wxJSONTYPE_UINT; - } - - wxJSON_ASSERT(data); - data->m_type = type; - - // clears complex objects of the old type - switch (oldType) { - case wxJSONTYPE_STRING: - data->m_valString.clear(); - break; - case wxJSONTYPE_ARRAY: - data->m_valArray.Clear(); - break; - case wxJSONTYPE_OBJECT: - data->m_valMap.clear(); - break; - case wxJSONTYPE_MEMORYBUFF: - // we first have to delete the actual memory buffer, if any - if (data->m_memBuff) { - delete data->m_memBuff; - data->m_memBuff = 0; - } - break; - default: - // there is not need to clear primitive types - break; - } - - // if the WXJSON_USE_CSTRING macro is not defined, the class forces - // C-string to be stored as wxString objects -#if !defined( WXJSON_USE_CSTRING ) - if (data->m_type == wxJSONTYPE_CSTRING) { - data->m_type = wxJSONTYPE_STRING; - } -#endif - return data; -} - -//! Return the line number of this JSON value object -/*! - The line number of a JSON value object is set to -1 when the - object is constructed. - The line number is set by the parser class, wxJSONReader, when - a JSON text is read from a stream or a string. - it is used when reading a comment line: comment lines that apear - on the same line as a value are considered \b inline comments of - the value. - */ -int -wxJSONValue::GetLineNo() const { - // return ZERO if there is not a referenced data structure - int n = 0; - wxJSONRefData *data = GetRefData(); - if (data != 0) { - n = data->m_lineNo; - } - return n; -} - -//! Set the line number of this JSON value object. -void -wxJSONValue::SetLineNo(int num) { - wxJSONRefData *data = COW();wxJSON_ASSERT(data); - data->m_lineNo = num; -} - -//! Set the pointer to the referenced data. -void -wxJSONValue::SetRefData(wxJSONRefData *data) { - m_refData = data; -} - -//! Increments the referenced data counter. -void -wxJSONValue::Ref(const wxJSONValue &clone) { - // nothing to be done - if (m_refData == clone.m_refData) - return; - - // delete reference to old data - UnRef(); - - // reference new data - if (clone.m_refData) { - m_refData = clone.m_refData; - ++(m_refData->m_refCount); - } -} - -//! Unreferences the shared data -/*! - The function decrements the number of shares in wxJSONRefData::m_refCount - and if it is ZERO, deletes the referenced data. - It is called by the destructor and by the copy-on-write functions. - */ -void -wxJSONValue::UnRef() { - if (m_refData) { - wxASSERT_MSG(m_refData->m_refCount > 0, wxT("invalid ref data count")); - - if (--m_refData->m_refCount == 0) { - delete m_refData; - m_refData = NULL; - } - } -} - -//! Makes an exclusive copy of shared data -void -wxJSONValue::UnShare() { - AllocExclusive(); -} - -//! Do a deep copy of the other object. -/*! - This function allocates a new ref-data structure and copies it - from the object \c other. - */ -void -wxJSONValue::DeepCopy(const wxJSONValue &other) { - UnRef(); - wxJSONRefData *data = CloneRefData(other.m_refData); - SetRefData(data); -} - -//! Return the pointer to the referenced data structure. -wxJSONRefData * -wxJSONValue::GetRefData() const { - return m_refData; -} - -//! Make a copy of the referenced data. -/*! - The function allocates a new instance of the wxJSONRefData - structure, copies the content of \c other and returns the pointer - to the newly created structure. - This function is called by the wxObject::UnRef() function - when a non-const member function is called on multiple - referenced data. - */ -wxJSONRefData * -wxJSONValue::CloneRefData(const wxJSONRefData *otherData) const { - wxJSON_ASSERT(otherData); - - // make a static cast to pointer-to-wxJSONRefData - const wxJSONRefData *other = otherData; - - // allocate a new instance of wxJSONRefData using the default - // ctor; we cannot use the copy ctor of a wxJSONRefData - wxJSONRefData *data = new wxJSONRefData(); - - // copy the referenced data structure's data members - data->m_type = other->m_type; - data->m_value = other->m_value; - data->m_commentPos = other->m_commentPos; - data->m_comments = other->m_comments; - data->m_lineNo = other->m_lineNo; - data->m_valString = other->m_valString; - data->m_valArray = other->m_valArray; - data->m_valMap = other->m_valMap; - - // if the data contains a wxMemoryBuffer object, then we have - // to make a deep copy of the buffer by allocating a new one because - // wxMemoryBuffer is not a copy-on-write structure - if (other->m_memBuff) { - data->m_memBuff = new wxMemoryBuffer(); - const void *ptr = data->m_memBuff->GetData(); - size_t len = data->m_memBuff->GetDataLen(); - if (data->m_memBuff && len) { - data->m_memBuff->AppendData(ptr, len); - } - } - - wxLogTrace(cowTraceMask, wxT("(%s) CloneRefData() PROGR: other=%d data=%d"), - __PRETTY_FUNCTION__, other->GetRefCount(), data->GetRefCount()); - - return data; -} - -//! Create a new data structure -/*! - The function allocates a new instance of the wxJSONRefData - structure and returns its pointer. - The type of the JSON value is set to wxJSONTYPE_INVALID (= - a not initialized value). - */ -wxJSONRefData * -wxJSONValue::CreateRefData() const { - wxJSONRefData *data = new wxJSONRefData(); - data->m_type = wxJSONTYPE_INVALID; - return data; -} - -//! Make sure the referenced data is unique -/*! - This function is called by all non-const member functions and makes - sure that the referenced data is unique by calling \b UnShare() - If the referenced data is shared acrosss other wxJSONValue instances, - the \c UnShare() function makes a private copy of the shared data. - */ -wxJSONRefData * -wxJSONValue::COW() { - wxLogTrace(cowTraceMask, wxT("(%s) COW() START data=%p data->m_count=%d"), - __PRETTY_FUNCTION__, GetRefData(), GetRefData()->GetRefCount()); - UnShare(); - wxLogTrace(cowTraceMask, wxT("(%s) COW() END data=%p data->m_count=%d"), - __PRETTY_FUNCTION__, GetRefData(), GetRefData()->GetRefCount()); - return GetRefData(); -} - -//! Makes a private copy of the referenced data -void -wxJSONValue::AllocExclusive() { - if (!m_refData) { - m_refData = CreateRefData(); - } else if (m_refData->GetRefCount() > 1) { - // note that ref is not going to be destroyed in this case - const wxJSONRefData *ref = m_refData; - UnRef(); - - // ... so we can still access it - m_refData = CloneRefData(ref); - } - //else: ref count is 1, we are exclusive owners of m_refData anyhow - - wxASSERT_MSG(m_refData && m_refData->GetRefCount() == 1, - wxT("wxObject::AllocExclusive() failed.")); -} - -//! Convert memory buffer object to a string representation. -/*/ - The fucntion returns a string representation of the data contained in the - memory buffer object \c buff. - The string is conposed of two hexadecimal digits for every byte contained - in the memory buffer; bytes are separated by a space character. - The string starts with the actual lenght of the data enclosed in parenthesis. - The string will contain \c len bytes if \c len is less than the length - of the actual data in \c buff. - Note that the (len) printed in the output referes to the length of the buffer - which may be greater than the length that has to be printed. - - \b Example: - This is an example of printing a memory buffer object that contains 10 bytes: - \code - 0x80974653 (10) 00 01 02 03 04 05 06 07 08 09 - \endcode - */ -wxString -wxJSONValue::MemoryBuffToString(const wxMemoryBuffer &buff, size_t len) { - size_t buffLen = buff.GetDataLen(); - void *ptr = buff.GetData(); - wxString s = MemoryBuffToString(ptr, MIN(buffLen, len), buffLen); - return s; -} - -//! Convert a binary memory buffer to a string representation. -/*/ - The function returns a string representation of the data contained in the - binary memory buffer pointed to by \c buff for \c len bytes. - The string is composed of two hexadecimal digits for every byte contained - in the memory buffer; bytes are separated by a space character. - The string starts with pointer to binary data followed by the lenght of the - data enclosed in parenthesis. - - \b Example: - This is an example of printing ten bytes from a memory buffer: - \code - 0x80974653 (10) 00 01 02 03 04 05 06 07 08 09 - \endcode - - @param buff the pointer to the memory buffer data - @len the length of the data that has to be printed - @actualLen the real lenght of the memory buffer that has to be printed - just afetr the pointer; may be greater than \c len. If this parameter - is -1 then it is equal to \c len - */ -wxString -wxJSONValue::MemoryBuffToString(const void *buff, size_t len, size_t actualLen) { - wxString s; - size_t buffLen = actualLen; - if (buffLen == (size_t) -1) { - buffLen = len; - } - s.Printf(wxT("%p (%u) "), buff, buffLen); - unsigned char *ptr = (unsigned char *) buff; - for (unsigned int i = 0; i < len; i++) { - unsigned char c = *ptr; - ++ptr; - // now convert the character - char c1 = c / 16; - char c2 = c % 16; - c1 += '0'; - c2 += '0'; - if (c1 > '9') { - c1 += 7; - } - if (c2 > '9') { - c2 += 7; - } - s.Append(c1, 1); - s.Append(c2, 1); - s.Append(' ', 1); // a space separates the bytes - } - return s; -} - -//! Compares two memory buffer objects -/*! - The function is the counterpart of the comparison operator == for two wxMemoryBuffer - objects. - You may noticed that the wxMemoryBuffer class does not define comparison operators so - if you write a code snippset like the following: - \code - wxMemoryBuffer b1; - wxMemoryBuffer b2; - b1.AppendData( "1234567890", 10 ); - b2.AppendData( "1234567890", 10 ); - bool r = b1 == b2; - \endcode - - you may expect that \b r is TRUE, because both objects contain the same data. - This is not true. The result you get is FALSE because the default comparison operator - is used, which just compares the data members of the class. - The data member is the pointer to the allocated memory that contains the data and - they are not equal. - This function uses the (fast) \b memcmp function to compare the actual data - contained in the nenory buffer objects thus doing a deep comparison. - The function returns the return value of \b memcmp: - - the memcmp() function returns an integer less than, equal to, or - greater than zero if the first n bytes of \c buff1 is found, respectively, to - be less than, to match, or be greater than the first n bytes of \c buff2. - */ -int -wxJSONValue::CompareMemoryBuff(const wxMemoryBuffer &buff1, const wxMemoryBuffer &buff2) { - int r; - size_t buff1Len = buff1.GetDataLen(); - size_t buff2Len = buff2.GetDataLen(); - if (buff1Len > buff2Len) { - r = 1; - } else if (buff1Len < buff2Len) { - r = -1; - } else { - r = memcmp(buff1.GetData(), buff2.GetData(), buff1Len); - } - return r; -} - -//! Compares a memory buffer object and a memory buffer -/*! - The function compares the data contained in a memory buffer object with a - memory buffer. - This function uses the (fast) \b memcmp function to compare the actual data - contained in the nenory buffer object thus doing a deep comparison. - The function returns the return value of \b memcmp: - - The memcmp() function returns an integer less than, equal to, or - greater than zero if the first n bytes of \c buff1 is found, respectively, to - be less than, to match, or be greater than the first n bytes of \c buff2. - */ -int -wxJSONValue::CompareMemoryBuff(const wxMemoryBuffer &buff1, const void *buff2) { - int r; - size_t buff1Len = buff1.GetDataLen(); - r = memcmp(buff1.GetData(), buff2, buff1Len); - return r; -} - -//! Converts an array of INTs to a memory buffer -/*! - This static function converts an array of INTs stored in a wxJSONvalue object - into a memory buffer object. - The wxJSONvalue object passed as parameter must be of type ARRAY and must contain - INT types whose values are between 0 and 255. - - Every element of the array si converted to a BYTE value and appended to the returned - wxMemoryBuffer object. The following rules apply in the conversion: - \li if \c value is not an ARRAY type, an empty memory buffer is returned - \li if the \c value array contains elements of type other than INT, those - elements are ignored - \li if the \c value array contains elements of type INT which value is outside the - range 0..255, those elements are ignored - \li if the \c value array contains only ignored elements an empty wxMemoryBuffer - object is returned. - - This function can be used to get a memory buffer object from valid JSON text. - Please note that the wxJSONReader cannot know which array of INTs represent a binary - memory buffer unless you use the \b wxJSON \e memory \e buffer extension in the writer and - in the reader. - */ -wxMemoryBuffer -wxJSONValue::ArrayToMemoryBuff(const wxJSONValue &value) { - wxMemoryBuffer buff; - if (value.IsArray()) { - int len = value.Size(); - for (int i = 0; i < len; i++) { - short int byte; - unsigned char c; - // we do not use opertaor [] because it is not const - // bool r = value[i].AsShort( byte ); - bool r = value.ItemAt(i).AsShort(byte); - if (r && (byte >= 0 && byte <= 255)) { - c = (unsigned char) byte; - buff.AppendByte(c); - } - } - } - return buff; -} - -/************************************************************************* - - 64-bits integer support - - *************************************************************************/ - -#if defined( wxJSON_64BIT_INT) - -//! \overload wxJSONValue() -wxJSONValue::wxJSONValue(wxInt64 i) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_INT);wxJSON_ASSERT(data); - if (data != 0) { - data->m_value.VAL_INT = i; - } -} - -//! \overload wxJSONValue() -wxJSONValue::wxJSONValue(wxUint64 ui) { - m_refData = 0; - wxJSONRefData *data = Init(wxJSONTYPE_UINT);wxJSON_ASSERT(data); - if (data != 0) { - data->m_value.VAL_UINT = ui; - } -} - -//! Return TRUE if the stored value is a 32-bits integer -/*! - This function is only available on 64-bits platforms and returns - TRUE if, and only if, the stored value is of type \b wxJSONTYPE_INT - and the numeric value fits in a 32-bits signed integer. - The function just calls IsLong() and returns the value returned by - that function. - The use of this function is deprecated: use \c IsLong() instead - */ -bool -wxJSONValue::IsInt32() const { - bool r = IsLong(); - return r; -} - -//! Return TRUE if the stored value is a unsigned 32-bits integer -/*! - This function is only available on 64-bits platforms and returns - TRUE if, and only if, the stored value is of type \b wxJSONTYPE_UINT - and the numeric value fits in a 32-bits unsigned integer. - The function just calls IsULong() and returns the value returned by - that function. - The use of this function is deprecated: use \c IsULong() instead - */ -bool -wxJSONValue::IsUInt32() const { - bool r = IsULong(); - return r; -} - -//! Return TRUE if the stored value is integer. -/*! - This function returns TRUE if the stored value is of - type signed integer. - In other words, the function returns TRUE if the \c wxJSONRefData::m_type - data member is of type \c wxJSONTYPE_INT - The function is only available if 64-bits integer support is enabled. - - \sa \ref json_internals_integer - */ -bool -wxJSONValue::IsInt64() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - bool r = false; - if (data->m_type == wxJSONTYPE_INT) { - r = true; - } - return r; -} - -//! Return TRUE if the stored value is a unsigned integer -/*! - This function returns TRUE if the stored value is of - type unsigned integer. - In other words, the function returns TRUE if the \c wxJSONRefData::m_type - data member is of type \c wxJSONTYPE_UINT. - The function is only available if 64-bits integer support is enabled. - - \sa \ref json_internals_integer - */ -bool -wxJSONValue::IsUInt64() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - bool r = false; - if (data->m_type == wxJSONTYPE_UINT) { - r = true; - } - return r; -} - -//! Returns the low-order 32 bits of the value as an integer -/*! - This function is only available on 64-bits platforms and returns - the low-order 32-bits of the integer stored in the JSON value. - Note that all integer types are stored as \b wx(U)Int64 data types by - the JSON value class and that the function does not check that the - numeric value fits in a 32-bit integer. - The function just calls AsLong() and casts the value in a wxInt32 data - type - - \sa \ref wxjson_tutorial_get - */ -wxInt32 -wxJSONValue::AsInt32() const { - wxInt32 i; - i = (wxInt32) AsLong(); - return i; -} - -//! Returns the low-order 32 bits of the value as an unsigned integer -/*! - This function is only available on 64-bits platforms and returns - the low-order 32-bits of the integer stored in the JSON value. - Note that all integer types are stored as \b wx(U)Int64 data types by - the JSON value class and that the function does not check that the - numeric value fits in a 32-bit integer. - The function just calls AsULong() and casts the value in a wxUInt32 data - type - - \sa \ref wxjson_tutorial_get - */ -wxUint32 -wxJSONValue::AsUInt32() const { - wxUint32 ui; - ui = (wxUint32) AsULong(); - return ui; -} - -//! Return the numeric value as a 64-bit integer. -/*! - This function is only available on 64-bits platforms and returns - the numeric value as a 64-bit integer. - - Note that the function does not check that the type of the - value is actually an integer and it just returns the content - of the wxJSONValueHolder union. - However, in debug builds, the function ASSERTs that the - type of the stored value is wxJSONTYPE_INT. - - \sa \ref json_internals_integer - \sa \ref wxjson_tutorial_get - */ -wxInt64 -wxJSONValue::AsInt64() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - wxInt64 i64 = data->m_value.m_valInt64; - - wxJSON_ASSERT(IsInt64()); // exapnds only in debug builds - return i64; -} - -//! Return the numeric value as a 64-bit unsigned integer. -/*! - This function is only available on 64-bits platforms and returns - the numeric value as a 64-bit unsigned integer. - - Note that the function does not check that the type of the - value is actually an integer and it just returns the content - of the wxJSONValueHolder union. - However, in debug builds, the function wxJSON_ASSERTs that the - type of the stored value is wxJSONTYPE_UINT. - - \sa \ref json_internals_integer - \sa \ref wxjson_tutorial_get - */ -wxUint64 -wxJSONValue::AsUInt64() const { - wxJSONRefData *data = GetRefData();wxJSON_ASSERT(data); - wxUint64 ui64 = data->m_value.m_valUInt64; - - wxJSON_ASSERT(IsUInt64()); // exapnds only in debug builds - return ui64; -} - -bool -wxJSONValue::AsInt32(wxInt32 &i32) const { - bool r = IsInt32(); - if (r) { - i32 = AsInt32(); - } - return r; -} - -bool -wxJSONValue::AsUInt32(wxUint32 &ui32) const { - bool r = IsUInt32(); - if (r) { - ui32 = AsUInt32(); - } - return r; -} - -bool -wxJSONValue::AsInt64(wxInt64 &i64) const { - bool r = IsInt64(); - if (r) { - i64 = AsInt64(); - } - return r; -} - -bool -wxJSONValue::AsUInt64(wxUint64 &ui64) const { - bool r = IsUInt64(); - if (r) { - ui64 = AsUInt64(); - } - return r; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(wxInt64 i) { - wxJSONValue v(i); - wxJSONValue &r = Append(v); - return r; -} - -//! \overload Append( const wxJSONValue& ) -wxJSONValue & -wxJSONValue::Append(wxUint64 ui) { - wxJSONValue v(ui); - wxJSONValue &r = Append(v); - return r; -} - -//! \overload operator = (int) -wxJSONValue & -wxJSONValue::operator=(wxInt64 i) { - wxJSONRefData *data = SetType(wxJSONTYPE_INT); - data->m_value.VAL_INT = i; - return *this; -} - -//! \overload operator = (int) -wxJSONValue & -wxJSONValue::operator=(wxUint64 ui) { - wxJSONRefData *data = SetType(wxJSONTYPE_UINT); - data->m_value.VAL_UINT = ui; - return *this; -} - -#endif // defined( wxJSON_64BIT_INT ) - -/* -{ -} -*/ diff --git a/src/jsonwriter.cpp b/src/jsonwriter.cpp deleted file mode 100644 index 1836bcc5..00000000 --- a/src/jsonwriter.cpp +++ /dev/null @@ -1,1225 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: jsonwriter.cpp -// Purpose: the wxJSONWriter class: a JSON text generator -// Author: Luciano Cattani -// Created: 2007/10/12 -// RCS-ID: $Id: jsonwriter.cpp,v 1.6 2008/03/03 19:05:47 luccat Exp $ -// Copyright: (c) 2007 Luciano Cattani -// Licence: wxWidgets licence -///////////////////////////////////////////////////////////////////////////// - -#ifdef __GNUG__ -#pragma implementation "jsonwriter.cpp" -#endif - -#include "wex/jsonwriter.h" - -#include -#include -#include -#include - -#if wxUSE_LOG_TRACE -static const wxChar* writerTraceMask = _T("traceWriter"); -#endif - -/*! \class wxJSONWriter - \brief The JSON document writer - - This class is a JSON document writer and it is used to write a - wxJSONValue object to an output stream or to a string object. - The ctor accepts some parameters which can be used to - change the style of the output. - The default output is in human-readable format that uses a three-space - indentation for object / array sub-items and separates every - value with a linefeed character. - - \par Examples - - Using the default writer constructor - - \code - // construct the JSON value object and add values to it - wxJSONValue root; - root["key1"] = "some value"; - ... - - // construct the string that will contain the JSON text - wxString str; - - // construct a JSON writer: use the default writer's settings - wxJSONWriter writer; - - // call the writer's Write() memberfunction - writer.Write( root, str ); - \endcode - - To write a JSON value object using a four-spaces indentation and forcing all - comment strings to apear before the value they refer to, use the following code: - \code - wxJSONWriter writer( wxJSONWRITER_STYLED | // want a styled output - wxJSONWRITER_WRITE_COMMENTS | // want comments in the document - wxJSONWRITER_COMMENTS_BEFORE, // force comments before value - 0, // initial indentation - 4); // indentation step - writer.Write( value, document ); - \endcode - - The following code construct a JSON writer that produces the most compact - text output but it is hard to read by humans: - - \code - wxJSONWriter writer( wxJSONWRITER_NONE ); - writer.Write( value, document ); - \endcode - - \par The two types of output objects - - You can write JSON text to two different kind of objects: - - \li a string object (\b wxString) - \li a stream object (\b wxOutputStream) - - When writing to a string object, the output is platform- and mode-dependent. - In ANSI builds, the JSON text output in the string object will - contain one-byte characters: the actual characters represented is - locale dependent. - In Unicode builds, the JSON text output in the string contains - wide characters which encoding format is platform dependent: UCS-2 in - Windows, UCS-4 in GNU/Linux. - Starting from wxWidgets version 2.9 the internal encoding for Unicode - builds in linux/unix systems is UTF-8. - - When writing to a stream object, the JSON text output is always - encoded in UTF-8 in both ANSI and Unicode builds. - In ANSI builds the user may want to suppress UTF-8 encoding so - that the JSON text can be stored in ANSI format. - Note that this is not valid JSON text unless all characters written - to the JSON text document are in the US-ASCII character ser (0x00..0x7F). - To know more read \ref wxjson_tutorial_unicode_ansi - - \par Efficiency - - In versions up to 1.0 the JSON writer wrote every character to the - output object (the string or the stream). - This is very inefficient becuase the writer converted each char to - UTF-8 when writing to streams but we have to note that only string values - have to be actually converted. - Special JSON characters, numbers and literals do not need the conversion - because they lay in the US-ASCII plane (0x00-0x7F) - and no conversion is needed as the UTF-8 encoding is the same as US-ASCII. - - For more info about the unicode topic see \ref wxjson_tutorial_unicode. - - \par The problem of writing doubles - - You can customize the ouput of doubles by specifing the format string - that has to be used by the JSON writer class. To know more about this issue - read \ref wxjson_tutorial_write_doubles - */ - -//! Ctor. -/*! - Construct the JSON writer object with the specified parameters. - Note that if \c styled is FALSE the indentation is totally suppressed - and the values of the other two parameters are simply ignored. - - \param indent the initial indentation in number of spaces. Default is ZERO. - If you specify the wxJSONWRITER_TAB_INDENT flag for the \e style, - this value referes to the number of TABs in the initial indentation - - \param step the indentation increment for new objects/arrays in number of spaces - (default is 3). - This value is ignored if you specify the wxJSONWRITER_TAB_INDENT flag for - the \e style: the indentation increment is only one TAB character. - - \param style this is a combination of the following constants OR'ed togheter: - \li wxJSONWRITER_NONE: no indentation is performed and no LF character is - written between values. - This style produces strict JSON text but it is hard to read by humans - \li wxJSONWRITER_STYLED: output is human-readable: values are separated by - LF characters and sub-items are indented. - This style produces strict JSON text that is easy to read by humans. - \li wxJSONWRITER_WRITE_COMMENTS: this flag force the writer to write C/C++ - comment strings, if any. The comments will be written in their original position. - C/C++ comments may not be recognized by other JSON implementations because - they are not strict JSON text. - \li wxJSONWRITER_COMMENTS_BEFORE: this flag force the writer to write C/C++ comments - always before the value they refer to. - In order for this style to take effect, you also have to specify the - wxJSONWRITER_WRITE_COMMENTS flag. - \li wxJSONWRITER_COMMENTS_AFTER: this flag force the writer to write C/C++ comments - always after the value they refer to. - In order for this style to take effect, you also have to specify the - wxJSONWRITER_WRITE_COMMENTS flag. - \li wxJSONWRITER_SPLIT_STRINGS: this flag cause the writer to split strings - in more than one line if they are too long. - \li wxJSONWRITER_NO_LINEFEEDS: this flag cause the JSON writer to not add - newlines between values. It is ignored if wxJSONWRITER_STYLED is not set. - This style produces strict JSON text. - \li wxJSONWRITER_ESCAPE_SOLIDUS: the solidus character (/) should only be - escaped if the JSON text is meant for embedding in HTML. - Unlike in older 0.x versions, it is disabled by default and this flag cause - the solidus char to be escaped. - This style produces strict JSON text. - \li wxJSONWRITER_MULTILINE_STRING:this is a multiline-string mode where newlines - and tabs are not escaped. This is not strict JSON, but it helps immensely when - manually editing json files with multiline strings - \li wxJSONWRITER_RECOGNIZE_UNSIGNED: this flag cause the JSON writer to prepend - a plus sign (+) to unsigned integer values. This is used by the wxJSON reader to - force the integer to be stored in an \b unsigned \b int. Note that this - feature may be incompatible with other JSON implementations. - \li wxJSONWRITER_TAB_INDENT: this flag cause the indentation of sub-objects / arrays - to be done using a TAB character instead of SPACES. - In order for this style to take effect, you also have to specify the - wxJSONWRITER_STYLED flag. - This style produces strict JSON text. - \li wxJSONWRITER_NO_INDENTATION: this flag cause the JSON writer to not add - indentation. It is ignored if wxJSONWRITER_STYLED is not set. - This style produces strict JSON text. - \li wxJSONWRITER_NOUTF8_STREAM: suppress UTF-8 conversion when writing string - values to the stream thus producing ANSI text output; only meaningfull in - ANSI builds, this flag is simply ignored in Unicode builds. - \li wxJSONWRITER_MEMORYBUFF: - - Note that for the style wxJSONWRITER_NONE the JSON text output is a bit - different from that of old 0.x versions although it is syntactically equal. - If you rely on the old JSON output formatting read the following page - \ref wxjson_tutorial_style_none. - To know more about the writer's styles see \ref wxjson_tutorial_style - */ -wxJSONWriter::wxJSONWriter(int style, int indent, int step) { - m_indent = indent; - m_step = step; - m_style = style; - m_noUtf8 = false; - if (m_style == wxJSONWRITER_NONE) { - m_indent = 0; - m_step = 0; - } - // set the default format string for doubles as - // 10 significant digits and suppress trailing ZEROes - SetDoubleFmtString("%.10g"); - -#if !defined( wxJSON_USE_UNICODE ) - // in ANSI builds we can suppress UTF-8 conversion for both the writer and the reader - if ( m_style == wxJSONWRITER_NOUTF8_STREAM ) { - m_noUtf8 = true; - } -#endif -} - -//! Dtor - does nothing -wxJSONWriter::~wxJSONWriter() { -} - -//! Write the JSONvalue object to a JSON text. -/*! - The two overloaded versions of this function let the user choose - the output object which can be: - - \li a string object (\b wxString) - \li a stream object ( \b wxOutputStream) - - The two types of output object are very different because the - text outputted is encoded in different formats depending on the - build mode. - When writing to a string object, the JSON text output is encoded - differently depending on the build mode and the platform. - Writing to a stream always produce UTF-8 encoded text. - To know more about this topic read \ref wxjson_tutorial_unicode. - - Also note that the Write() function does not return a status code. - If you are writing to a string, you do not have to warry about this - issue: no errors can occur when writing to strings. - On the other hand, wehn writing to a stream there could be errors - in the write operation. - If an error occurs, the \c Write(9 function immediatly returns - without trying further output operations. - You have to check the status of the stream by calling the stream's - memberfunctions. Example: - - \code - // construct the JSON value object and add values to it - wxJSONValue root; - root["key1"] = "some value"; - - // write to a stream - wxMemoryOutputStream mem; - wxJSONWriter writer; - writer.Write( root, mem ); - wxStreamError err = mem.GetLastError(); - if ( err != wxSTREAM_NO_ERROR ) { - MessageBox( _T("ERROR: cannot write the JSON text output")); - } - \endcode - */ -void -wxJSONWriter::Write(const wxJSONValue &value, wxString &str) { -#if !defined( wxJSON_USE_UNICODE ) - // in ANSI builds output to a string never use UTF-8 conversion - bool noUtf8_bak = m_noUtf8; // save the current setting - m_noUtf8 = true; -#endif - - wxMemoryOutputStream os; - Write(value, os); - - // get the address of the buffer - wxFileOffset len = os.GetLength(); - wxStreamBuffer *osBuff = os.GetOutputStreamBuffer(); - void *buffStart = osBuff->GetBufferStart(); - - if (m_noUtf8) { - str = wxString::From8BitData((const char *) buffStart, len); - } else { - str = wxString::FromUTF8((const char *) buffStart, len); - } -#if !defined( wxJSON_USE_UNICODE ) - m_noUtf8 = noUtf8_bak; // restore the old setting -#endif -} - -//! \overload Write( const wxJSONValue&, wxString& ) -void -wxJSONWriter::Write(const wxJSONValue &value, wxOutputStream &os) { - m_level = 0; - DoWrite(os, value, 0, false); -} - -//! Set the format string for double values. -/*! - This function sets the format string used for printing double values. - Double values are outputted to JSON text using the \b snprintf function - with a default format string of: - \code - %.10g - \endcode - which prints doubles with a precision of 10 decimal digits and suppressing - trailing ZEROes. - - Note that the parameter is a pointer to \b char and not to \b wxChar. This - is because the JSON writer always procudes UTF-8 encoded text and decimal - digits in UTF-8 are made of only one UTF-8 code-unit (1 byte). - */ -void -wxJSONWriter::SetDoubleFmtString(const char *fmt) { - m_fmt = (char *) fmt; -} - -//! Perform the real write operation. -/*! - This is a recursive function that gets the type of the \c value object and - calls several protected functions depending on the type: - - \li \c WriteNullvalue for type NULL - \li \c WriteStringValue() for STRING and CSTRING types - \li \c WriteIntValue for INT types - \li \c WriteUIntValue for UINT types - \li \c WriteBoolValue for BOOL types - \li \c WriteDoubleValue for DOUBLE types - \li \c WriteMemoryBuff for MEMORYBUFF types - - If the value is an array or key/value map (types ARRAY and OBJECT), the function - iterates through all JSON value object in the array/map and calls itself for every - item in the container. - */ -int -wxJSONWriter::DoWrite(wxOutputStream &os, const wxJSONValue &value, const wxString *key, bool comma) { - // note that this function is recursive - - // some variables that cannot be allocated in the switch statement - const wxJSONInternalMap *map = 0; - int size; - m_colNo = 1; - m_lineNo = 1; - // determine the comment position; it is one of: - // - // wxJSONVALUE_COMMENT_BEFORE - // wxJSONVALUE_COMMENT_AFTER - // wxJSONVALUE_COMMENT_INLINE - // - // or -1 if comments have not to be written - int commentPos = -1; - if (value.GetCommentCount() > 0 && (m_style & wxJSONWRITER_WRITE_COMMENTS)) { - commentPos = value.GetCommentPos(); - if ((m_style & wxJSONWRITER_COMMENTS_BEFORE) != 0) { - commentPos = wxJSONVALUE_COMMENT_BEFORE; - } else if ((m_style & wxJSONWRITER_COMMENTS_AFTER) != 0) { - commentPos = wxJSONVALUE_COMMENT_AFTER; - } - } - - int lastChar = 0; // check if WriteComment() writes the last LF char - - // first write the comment if it is BEFORE - if (commentPos == wxJSONVALUE_COMMENT_BEFORE) { - lastChar = WriteComment(os, value, true); - if (lastChar < 0) { - return lastChar; - } else if (lastChar != '\n') { - WriteSeparator(os); - } - } - - lastChar = WriteIndent(os); - if (lastChar < 0) { - return lastChar; - } - - // now write the key if it is not NULL - if (key) { - lastChar = WriteKey(os, *key); - } - if (lastChar < 0) { - return lastChar; - } - - // now write the value - wxJSONInternalMap::const_iterator it; // declare the map object - long int count = 0; - - wxJSONType t = value.GetType(); - switch (t) { - case wxJSONTYPE_INVALID: - WriteInvalid(os); - wxFAIL_MSG(_T("wxJSONWriter::WriteEmpty() cannot be called (not a valid JSON text")); - break; - - case wxJSONTYPE_INT: - case wxJSONTYPE_SHORT: - case wxJSONTYPE_LONG: - case wxJSONTYPE_INT64: - lastChar = WriteIntValue(os, value); - break; - - case wxJSONTYPE_UINT: - case wxJSONTYPE_USHORT: - case wxJSONTYPE_ULONG: - case wxJSONTYPE_UINT64: - lastChar = WriteUIntValue(os, value); - break; - - case wxJSONTYPE_NULL: - lastChar = WriteNullValue(os); - break; - case wxJSONTYPE_BOOL: - lastChar = WriteBoolValue(os, value); - break; - - case wxJSONTYPE_DOUBLE: - lastChar = WriteDoubleValue(os, value); - break; - - case wxJSONTYPE_STRING: - case wxJSONTYPE_CSTRING: - lastChar = WriteStringValue(os, value.AsString()); - break; - - case wxJSONTYPE_MEMORYBUFF: - lastChar = WriteMemoryBuff(os, value.AsMemoryBuff()); - break; - - case wxJSONTYPE_ARRAY: - ++m_level; - os.PutC('['); - // the inline comment for objects and arrays are printed in the open char - if (commentPos == wxJSONVALUE_COMMENT_INLINE) { - commentPos = -1; // we have already written the comment - lastChar = WriteComment(os, value, false); - if (lastChar < 0) { - return lastChar; - } - if (lastChar != '\n') { - lastChar = WriteSeparator(os); - } - } else { // comment is not to be printed inline, so write a LF - lastChar = WriteSeparator(os); - if (lastChar < 0) { - return lastChar; - } - } - - // now iterate through all sub-items and call DoWrite() recursively - size = value.Size(); - for (int i = 0; i < size; i++) { - bool comma_tmp = false; - if (i < size - 1) { - comma_tmp = true; - } - wxJSONValue v = value.ItemAt(i); - lastChar = DoWrite(os, v, 0, comma_tmp); - if (lastChar < 0) { - return lastChar; - } - } - --m_level; - lastChar = WriteIndent(os); - if (lastChar < 0) { - return lastChar; - } - os.PutC(']'); - break; - - case wxJSONTYPE_OBJECT: - ++m_level; - - os.PutC('{'); - // the inline comment for objects and arrays are printed in the open char - if (commentPos == wxJSONVALUE_COMMENT_INLINE) { - commentPos = -1; // we have already written the comment - lastChar = WriteComment(os, value, false); - if (lastChar < 0) { - return lastChar; - } - if (lastChar != '\n') { - WriteSeparator(os); - } - } else { - lastChar = WriteSeparator(os); - } - - map = wxJSONValueAsMap(value); - size = value.Size(); - count = 0; - for (it = map->begin(); it != map->end(); ++it) { - // get the key and the value - wxString key_tmp = it->first; - const wxJSONValue &v = it->second; - bool comma_tmp = false; - if (count < size - 1) { - comma_tmp = true; - } - lastChar = DoWrite(os, v, &key_tmp, comma_tmp); - if (lastChar < 0) { - return lastChar; - } - count++; - } - --m_level; - lastChar = WriteIndent(os); - if (lastChar < 0) { - return lastChar; - } - os.PutC('}'); - break; - - default: - // a not yet defined wxJSONType: we FAIL - wxFAIL_MSG(_T("wxJSONWriter::DoWrite() undefined wxJSONType type")); - break; - } - - // writes the comma character before the inline comment - if (comma) { - os.PutC(','); - } - - if (commentPos == wxJSONVALUE_COMMENT_INLINE) { - lastChar = WriteComment(os, value, false); - if (lastChar < 0) { - return lastChar; - } - } else if (commentPos == wxJSONVALUE_COMMENT_AFTER) { - WriteSeparator(os); - lastChar = WriteComment(os, value, true); - if (lastChar < 0) { - return lastChar; - } - } - if (lastChar != '\n') { - lastChar = WriteSeparator(os); - } - return lastChar; -} - -//! Write the comment strings, if any. -int -wxJSONWriter::WriteComment(wxOutputStream &os, const wxJSONValue &value, bool indent) { - // the function returns the last character written which should be - // a LF char or -1 in case of errors - // if nothing is written, returns ZERO - int lastChar = 0; - - // only write comments if the style include the WRITE_COMMENTS flag - if ((m_style & wxJSONWRITER_WRITE_COMMENTS) == 0) { - return lastChar; - } - - const wxArrayString cmt = value.GetCommentArray(); - int cmtSize = cmt.GetCount(); - for (int i = 0; i < cmtSize; i++) { - if (indent) { - WriteIndent(os); - } else { - os.PutC('\t'); - } - WriteString(os, cmt[i]); - lastChar = cmt[i].Last(); - if (lastChar != '\n') { - os.PutC('\n'); - lastChar = '\n'; - } - } - return lastChar; -} - -//! Writes the indentation to the JSON text. -/*! - The two functions write the indentation as \e spaces in the JSON output - text. When called with a int parameter, the function - writes the specified number of spaces. - If no parameter is given, the function computes the number of spaces - using the following formula: - If the wxJSONWRITER_TAB_INDENT flag is used in the writer's cnstructor, - the function calls WriteTabIndent(). - - The function also checks that wxJSONWRITER_STYLED is set and the - wxJSONWRITER_NO_INDENTATION is not set. - */ -int -wxJSONWriter::WriteIndent(wxOutputStream &os) { - int lastChar = WriteIndent(os, m_level); - return lastChar; -} - -//! Write the specified number of indentation (spaces or tabs) -/*! - The function is called by WriteIndent() and other writer's functions. - It writes the indentation as specified in the \c num parameter which is - the actual \b level of annidation. - The function checks if wxJSONWRITER_STYLED is set: if not, no indentation - is performed. - Also, the function checks if wxJSONWRITER_TAB_INDENT is set: if it is, - indentation is done by writing \b num TAB characters otherwise, - it is performed by writing a number of spaces computed as: - \code - numSpaces = m_indent + ( m_step * num ) - \endcode - - */ -int -wxJSONWriter::WriteIndent(wxOutputStream &os, int num) { - int lastChar = 0; - if (!(m_style & wxJSONWRITER_STYLED) || (m_style & wxJSONWRITER_NO_INDENTATION)) { - return lastChar; - } - - int numChars = m_indent + (m_step * num); - char c = ' '; - if (m_style & wxJSONWRITER_TAB_INDENT) { - c = '\t'; - numChars = num; - } - - for (int i = 0; i < numChars; i++) { - os.PutC(c); - if (os.GetLastError() != wxSTREAM_NO_ERROR) { - return -1; - } - } - return c; -} - -//! Write the provided string to the output object. -/*! - The function writes the string \c str to the output object that - was specified in the wxJSONWriter::Write() function. - The function may split strings in two or more lines if the - string contains LF characters if the \c m_style data member contains - the wxJSONWRITER_SPLIT_STRING flag. - - The function does not actually write the string: for every character - in the provided string the function calls WriteChar() which does - the actual character output. - - The function returns ZERO on success or -1 in case of errors. - */ -int -wxJSONWriter::WriteStringValue(wxOutputStream &os, const wxString &str) { - // JSON values of type STRING are written by converting the whole string - // to UTF-8 and then copying the UTF-8 buffer to the 'os' stream - // one byte at a time and processing them - os.PutC('\"'); // open quotes - - // the buffer that has to be written is either UTF-8 or ANSI c_str() depending - // on the 'm_noUtf8' flag - char *writeBuff = 0; - wxCharBuffer utf8CB = str.ToUTF8(); // the UTF-8 buffer -#if !defined( wxJSON_USE_UNICODE ) - wxCharBuffer ansiCB( str.c_str()); // the ANSI buffer - if ( m_noUtf8 ) { - writeBuff = ansiCB.data(); - } - else { - writeBuff = utf8CB.data(); - } -#else - writeBuff = utf8CB.data(); -#endif - - // NOTE: in ANSI builds UTF-8 conversion may fail (see samples/test5.cpp, - // test 7.3) although I do not know why - if (writeBuff == 0) { - const char *err = ""; - os.Write(err, strlen(err)); - return 0; - } - size_t len = strlen(writeBuff); - int lastChar = 0; - - // store the column at which the string starts - // splitting strings only happen if the string starts within - // column wxJSONWRITER_LAST_COL (default 50) - // see 'include/wx/json_defs.h' for the defines - int tempCol = m_colNo; - - // now write the UTF8 buffer processing the bytes - size_t i; - for (i = 0; i < len; i++) { - bool shouldEscape = false; - unsigned char ch = *writeBuff; - ++writeBuff; // point to the next byte - - // the escaped character - char escCh = 0; - - // for every character we have to check if it is a character that - // needs to be escaped: note that characters that should be escaped - // may be not if some writer's flags are specified - switch (ch) { - case '\"': // quotes - shouldEscape = true; - escCh = '\"'; - break; - case '\\': // reverse solidus - shouldEscape = true; - escCh = '\\'; - break; - case '/': // solidus - shouldEscape = true; - escCh = '/'; - break; - case '\b': // backspace - shouldEscape = true; - escCh = 'b'; - break; - case '\f': // formfeed - shouldEscape = true; - escCh = 'f'; - break; - case '\n': // newline - shouldEscape = true; - escCh = 'n'; - break; - case '\r': // carriage-return - shouldEscape = true; - escCh = 'r'; - break; - case '\t': // horizontal tab - shouldEscape = true; - escCh = 't'; - break; - default: - shouldEscape = false; - break; - } // end switch - - // if the character is a control character that is not identified by a - // lowercase letter, we should escape it - if (!shouldEscape && ch < 32) { - char b[8]; - snprintf(b, 8, "\\u%04X", (int) ch); - os.Write(b, 6); - if (os.GetLastError() != wxSTREAM_NO_ERROR) { - return -1; - } - } - - // the char is not a control character - else { - // some characters that should be escaped are not escaped - // if the writer was constructed with some flags - if (shouldEscape && !(m_style & wxJSONWRITER_ESCAPE_SOLIDUS)) { - if (ch == '/') { - shouldEscape = false; - } - } - if (shouldEscape && (m_style & wxJSONWRITER_MULTILINE_STRING)) { - if (ch == '\n' || ch == '\t') { - shouldEscape = false; - } - } - - // now write the character prepended by ESC if it should be escaped - if (shouldEscape) { - os.PutC('\\'); - os.PutC(escCh); - if (os.GetLastError() != wxSTREAM_NO_ERROR) { - return -1; - } - } else { - // a normal char or a UTF-8 units: write the character - os.PutC(ch); - if (os.GetLastError() != wxSTREAM_NO_ERROR) { - return -1; - } - } - } - - // check if SPLIT_STRING flag is set and if the string has to - // be splitted - if ((m_style & wxJSONWRITER_STYLED) && (m_style & wxJSONWRITER_SPLIT_STRING)) { - // split the string if the character written is LF - if (ch == '\n') { - // close quotes and CR - os.Write("\"\n", 2); - lastChar = WriteIndent(os, m_level + 2); // write indentation - os.PutC('\"'); // reopen quotes - if (lastChar < 0) { - return lastChar; - } - } - // split the string only if there is at least wxJSONWRITER_MIN_LENGTH - // character to write and the character written is a punctuation or space - // BUG: the following does not work because the columns are not counted - else if ((m_colNo >= wxJSONWRITER_SPLIT_COL) - && (tempCol <= wxJSONWRITER_LAST_COL)) { - if (IsSpace(ch) || IsPunctuation(ch)) { - if (len - i > wxJSONWRITER_MIN_LENGTH) { - // close quotes and CR - os.Write("\"\n", 2); - lastChar = WriteIndent(os, m_level + 2); // write indentation - os.PutC('\"'); // reopen quotes - if (lastChar < 0) { - return lastChar; - } - } - } - } - } - } // end for - os.PutC('\"'); // close quotes - return 0; -} - -//! Write a generic string -/*! - The function writes the wxString object \c str to the output object. - The string is written as is; you cannot use it to write JSON strings - to the output text. - The function converts the string \c str to UTF-8 and writes the buffer.. - */ -int -wxJSONWriter::WriteString(wxOutputStream &os, const wxString &str) { - wxLogTrace(writerTraceMask, _T("(%s) string to write=%s"), - __PRETTY_FUNCTION__, str.c_str()); - int lastChar = 0; - char *writeBuff = 0; - - // the buffer that has to be written is either UTF-8 or ANSI c_str() depending - // on the 'm_noUtf8' flag - wxCharBuffer utf8CB = str.ToUTF8(); // the UTF-8 buffer -#if !defined( wxJSON_USE_UNICODE ) - wxCharBuffer ansiCB( str.c_str()); // the ANSI buffer - - if ( m_noUtf8 ) { - writeBuff = ansiCB.data(); - } - else { - writeBuff = utf8CB.data(); - } -#else - writeBuff = utf8CB.data(); -#endif - - // NOTE: in ANSI builds UTF-8 conversion may fail (see samples/test5.cpp, - // test 7.3) although I do not know why - if (writeBuff == 0) { - const char *err = ""; - os.Write(err, strlen(err)); - return 0; - } - size_t len = strlen(writeBuff); - - os.Write(writeBuff, len); - if (os.GetLastError() != wxSTREAM_NO_ERROR) { - return -1; - } - - wxLogTrace(writerTraceMask, _T("(%s) result=%d"), - __PRETTY_FUNCTION__, lastChar); - return lastChar; -} - -//! Write the NULL JSON value to the output stream. -/*! - The function writes the \b null literal string to the output stream. - */ -int -wxJSONWriter::WriteNullValue(wxOutputStream &os) { - os.Write("null", 4); - if (os.GetLastError() != wxSTREAM_NO_ERROR) { - return -1; - } - return 0; -} - -//! Writes a value of type INT. -/*! - This function is called for every value objects of INT type. - This function uses the \n snprintf function to get the US-ASCII - representation of the integer and simply copy it to the output stream. - Returns -1 on stream errors or ZERO if no errors. - */ -int -wxJSONWriter::WriteIntValue(wxOutputStream &os, const wxJSONValue &value) { - int r = 0; - char buffer[32]; // need to store 64-bits integers (max 20 digits) - size_t len; - - wxJSONRefData *data = value.GetRefData(); - wxASSERT(data); - -#if defined( wxJSON_64BIT_INT ) -#if wxCHECK_VERSION(2, 9, 0) || !defined( wxJSON_USE_UNICODE ) - // this is fine for wxW 2.9 and for wxW 2.8 ANSI - snprintf(buffer, 32, "%" wxLongLongFmtSpec "d", - data->m_value.m_valInt64); -#else - // this is for wxW 2.8 Unicode: in order to use the cross-platform - // format specifier, we use the wxString's sprintf() function and then - // convert to UTF-8 before writing to the stream - wxString s; - s.Printf( _T("%") wxLongLongFmtSpec _T("d"), - data->m_value.m_valInt64 ); - wxCharBuffer cb = s.ToUTF8(); - const char* cbData = cb.data(); - len = strlen( cbData ); - wxASSERT( len < 32 ); - memcpy( buffer, cbData, len ); - buffer[len] = 0; -#endif -#else - snprintf( buffer, 32, "%ld", data->m_value.m_valLong ); -#endif - len = strlen(buffer); - os.Write(buffer, len); - if (os.GetLastError() != wxSTREAM_NO_ERROR) { - r = -1; - } - return r; -} - -//! Writes a value of type UNSIGNED INT. -/*! - This function is called for every value objects of UINT type. - This function uses the \n snprintf function to get the US-ASCII - representation of the integer and simply copy it to the output stream. - The function prepends a \b plus \b sign if the \c wxJSONWRITER_RECOGNIZE_UNSIGNED - flag is set in the \c m_flags data member. - Returns -1 on stream errors or ZERO if no errors. - */ -int -wxJSONWriter::WriteUIntValue(wxOutputStream &os, const wxJSONValue &value) { - int r = 0; - size_t len; - - // prepend a plus sign if the style specifies that unsigned integers - // have to be recognized by the JSON reader - if (m_style & wxJSONWRITER_RECOGNIZE_UNSIGNED) { - os.PutC('+'); - } - - char buffer[32]; // need to store 64-bits integers (max 20 digits) - wxJSONRefData *data = value.GetRefData(); - wxASSERT(data); - -#if defined( wxJSON_64BIT_INT ) -#if wxCHECK_VERSION(2, 9, 0) || !defined( wxJSON_USE_UNICODE ) - // this is fine for wxW 2.9 and for wxW 2.8 ANSI - snprintf(buffer, 32, "%" wxLongLongFmtSpec "u", - data->m_value.m_valUInt64); -#else - // this is for wxW 2.8 Unicode: in order to use the cross-platform - // format specifier, we use the wxString's sprintf() function and then - // convert to UTF-8 before writing to the stream - wxString s; - s.Printf( _T("%") wxLongLongFmtSpec _T("u"), - data->m_value.m_valInt64 ); - wxCharBuffer cb = s.ToUTF8(); - const char* cbData = cb.data(); - len = strlen( cbData ); - wxASSERT( len < 32 ); - memcpy( buffer, cbData, len ); - buffer[len] = 0; -#endif -#else - snprintf( buffer, 32, "%lu", data->m_value.m_valULong ); -#endif - len = strlen(buffer); - os.Write(buffer, len); - if (os.GetLastError() != wxSTREAM_NO_ERROR) { - r = -1; - } - return r; -} - -//! Writes a value of type DOUBLE. -/*! - This function is called for every value objects of DOUBLE type. - This function uses the \n snprintf function to get the US-ASCII - representation of the integer and simply copy it to the output stream. - Returns -1 on stream errors or ZERO if no errors. - - Note that writing a double to a decimal ASCII representation could - lay to unexpected results depending on the format string used in the - conversion. - See SetDoubleFmtString for details. - */ -int -wxJSONWriter::WriteDoubleValue(wxOutputStream &os, const wxJSONValue &value) { - int r = 0; - - char buffer[32]; - wxJSONRefData *data = value.GetRefData(); - wxASSERT(data); - snprintf(buffer, 32, m_fmt, data->m_value.m_valDouble); - size_t len = strlen(buffer); - os.Write(buffer, len); - if (os.GetLastError() != wxSTREAM_NO_ERROR) { - r = -1; - } - return r; -} - -//! Writes a value of type BOOL. -/*! - This function is called for every value objects of BOOL type. - This function prints the literals \b true or \b false depending on the - value in \c value. - Returns -1 on stream errors or ZERO if no errors. - */ -int -wxJSONWriter::WriteBoolValue(wxOutputStream &os, const wxJSONValue &value) { - int r = 0; - const char *f = "false"; - const char *t = "true"; - wxJSONRefData *data = value.GetRefData(); - wxASSERT(data); - - const char *c = f; // defaults to FALSE - - if (data->m_value.m_valBool) { - c = t; - } - - size_t len = strlen(c); - os.Write(c, len); - if (os.GetLastError() != wxSTREAM_NO_ERROR) { - r = -1; - } - return r; -} - -//! Write the key of a key/value element to the output stream. -int -wxJSONWriter::WriteKey(wxOutputStream &os, const wxString &key) { - wxLogTrace(writerTraceMask, _T("(%s) key write=%s"), - __PRETTY_FUNCTION__, key.c_str()); - - int lastChar = WriteStringValue(os, key); - os.Write(" : ", 3); - return lastChar; -} - -//! Write the invalid JSON value to the output stream. -/*! - An invalid wxJSONValue is a value that was not initialized and it is - an error. You should never write invalid values to JSON text because - the output is not valid JSON text. - Note that the NULL value is a legal JSON text and it is written: - \code - null - \endcode - - This function writes a non-JSON text to the output stream: - \code - - \endcode - In debug mode, the function always fails with an wxFAIL_MSG failure. - */ -int -wxJSONWriter::WriteInvalid(wxOutputStream &os) { - wxFAIL_MSG(_T("wxJSONWriter::WriteInvalid() cannot be called (not a valid JSON text")); - int lastChar = 0; - os.Write("", 9); - return lastChar; -} - -//! Write a JSON value of type \e memory \e buffer -/*! - The type wxJSONTYPE_MEMORYBUFF is a \b wxJSON extension that is not correctly read by - other JSON implementations. - By default, the function writes such a type as an array of INTs as follows: - \code - [ 0,32,45,255,6,...] - \endcode - If the writer object was constructed using the \c wxJSONWRITER_MEMORYBUFF flag, then - the output is much more compact and recognized by the \b wxJSON reader as a memory buffer - type: - \code - '00203FFF06..' - \endcode - - */ -int -wxJSONWriter::WriteMemoryBuff(wxOutputStream &os, const wxMemoryBuffer &buff) { -#define MAX_BYTES_PER_ROW 20 - char str[16]; - - // if STYLED and SPLIT_STRING flags are set, the function writes 20 bytes on every row - // the following is the counter of bytes written. - // the string is splitted only for the special meory buffer type, not for array of INTs - int bytesWritten = 0; - bool splitString = false; - if ((m_style & wxJSONWRITER_STYLED) && - (m_style & wxJSONWRITER_SPLIT_STRING)) { - splitString = true; - } - - size_t buffLen = buff.GetDataLen(); - unsigned char *ptr = (unsigned char *) buff.GetData(); - wxASSERT(ptr); - char openChar = '\''; - char closeChar = '\''; - bool asArray = false; - - if ((m_style & wxJSONWRITER_MEMORYBUFF) == 0) { - // if the special flag is not specified, write as an array of INTs - openChar = '['; - closeChar = ']'; - asArray = true; - } - // write the open character - os.PutC(openChar); - - for (size_t i = 0; i < buffLen; i++) { - unsigned char c = *ptr; - ++ptr; - - if (asArray) { - snprintf(str, 14, "%d", c); - size_t len = strlen(str); - wxASSERT(len <= 3); - wxASSERT(len >= 1); - str[len] = ','; - // do not write the comma char for the last element - if (i < buffLen - 1) { - ++len; - } - os.Write(str, len); - if (os.GetLastError() != wxSTREAM_NO_ERROR) { - return -1; - } - } else { - // now convert the byte in two hex digits - char c1 = c / 16; - char c2 = c % 16; - c1 += '0'; - c2 += '0'; - if (c1 > '9') { - c1 += 7; - } - if (c2 > '9') { - c2 += 7; - } - os.PutC(c1); - os.PutC(c2); - if (os.GetLastError() != wxSTREAM_NO_ERROR) { - return -1; - } - if (splitString) { - ++bytesWritten; - } - - if ((bytesWritten >= MAX_BYTES_PER_ROW) && ((buffLen - i) >= 5)) { - // split the string if we wrote 20 bytes, but only is we have to - // write at least 5 bytes - os.Write("\'\n", 2); - int lastChar = WriteIndent(os, m_level + 2); // write indentation - os.PutC('\''); // reopen quotes - if (lastChar < 0) { - return lastChar; - } - bytesWritten = 0; - } - } - } - - // write the close character - os.PutC(closeChar); - return closeChar; -} - -//! Writes the separator between values -/*! - The function is called when a value has been written to the JSON - text output and it writes the separator character: LF. - The LF char is actually written only if the wxJSONWRITER_STYLED flag - is specified and wxJSONWRITER_NO_LINEFEEDS is not set. - - Returns the last character written which is LF itself or -1 in case - of errors. Note that LF is returned even if the character is not - actually written. - */ -int -wxJSONWriter::WriteSeparator(wxOutputStream &os) { - int lastChar = '\n'; - if ((m_style & wxJSONWRITER_STYLED) && !(m_style & wxJSONWRITER_NO_LINEFEEDS)) { - os.PutC('\n'); - } - return lastChar; -} - -//! Returns TRUE if the character is a space character. -bool -wxJSONWriter::IsSpace(wxChar ch) { - bool r = false; - switch (ch) { - case ' ': - case '\t': - case '\r': - case '\f': - case '\n': - r = true; - break; - default: - break; - } - return r; -} - -//! Returns TRUE if the character if a puctuation character -bool -wxJSONWriter::IsPunctuation(wxChar ch) { - bool r = false; - switch (ch) { - case '.': - case ',': - case ';': - case ':': - case '!': - case '?': - r = true; - break; - default: - break; - } - return r; -} - -/* -{ -} -*/ diff --git a/src/plot/plaxis.cpp b/src/plot/plaxis.cpp index 9a2ea3f2..47021d33 100644 --- a/src/plot/plaxis.cpp +++ b/src/plot/plaxis.cpp @@ -669,14 +669,25 @@ void wxPLTimeAxis::RecalculateTicksAndLabel() { //We need to figure out whether we are looking at hours, days, or months, and label the graph appropriately. wxDateTime timeKeeper(1, wxDateTime::Jan, 1971, 0, 0, 0); // works all time zones + double world_len = m_max - m_min; double time = m_min; + + // to skip leap years (SAM issue 289) - scale to first year + int m_min_offset = m_min / 8760; + double m_min_scaled = (double)((int)m_min % 8760); // m_min and m_max always based on 8760 (365 days with no leap years) + double m_max_scaled = (double)((int)m_max % 8760); // m_min and m_max always based on 8760 (365 days with no leap years) + if (m_max_scaled <= m_min_scaled) m_max_scaled += 8760; // handle year end points + + time = m_min_scaled; + timeKeeper.Add(wxTimeSpan::Minutes(60 * time)); // Handle DST. if (timeKeeper.IsDST()) timeKeeper.Subtract(wxTimeSpan::Hour()); + if (world_len <= 72) { if (floor(time) != time) { timeKeeper.Add(wxTimeSpan::Minutes(60 * (floor(time) + 2 - time))); @@ -700,11 +711,12 @@ void wxPLTimeAxis::RecalculateTicksAndLabel() { timeKeeper.Add(wxTimeSpan::Hour()); timeKeeper2.Add(wxTimeSpan::Hour()); } - if (timeKeeper.GetDay() == timeKeeper2.GetDay()) m_timeLabel = timeKeeper.Format("%b %d"); - else + else if (timeKeeper.GetMonth() == timeKeeper2.GetMonth()) m_timeLabel = timeKeeper.Format("%b %d") + "-" + timeKeeper2.Format("%d"); + else + m_timeLabel = timeKeeper.Format("%b %d") + "-" + timeKeeper2.Format("%b %d"); do { m_tickList.push_back(TickData(time, timeKeeper.Format("%H"), TickData::LARGE)); @@ -741,13 +753,18 @@ void wxPLTimeAxis::RecalculateTicksAndLabel() { } do { - m_tickList.push_back(TickData(time, timeKeeper.Format("%b %d"), TickData::NONE)); + auto str = timeKeeper.Format("%b %d"); +// m_tickList.push_back(TickData(time, str, TickData::NONE)); + m_tickList.push_back(TickData(time + m_min_offset*8760, str, TickData::NONE)); time += 12; - if (time < m_max) - m_tickList.push_back(TickData(time, wxEmptyString, TickData::LARGE)); // midnight +// if (time < m_max) + if (time < m_max_scaled) + m_tickList.push_back(TickData(time + m_min_offset * 8760, wxEmptyString, TickData::LARGE)); // midnight +// m_tickList.push_back(TickData(time, wxEmptyString, TickData::LARGE)); // midnight time += 12; timeKeeper.Add(wxTimeSpan::Hours(24)); - } while (time < m_max); + } while (time < m_max_scaled); +// } while (time < m_max); } else { //Assume day endpoints. //Only Label Months @@ -763,13 +780,16 @@ void wxPLTimeAxis::RecalculateTicksAndLabel() { timeKeeper2.Add(wxTimeSpan::Day()); } - m_tickList.push_back(TickData(time + daysVisibleInMonth * 24.0f, wxEmptyString, TickData::LARGE)); - int endMonthHours = time + daysVisibleInMonth * 24.0f; //00:00 on first of next month. +// m_tickList.push_back(TickData(time + daysVisibleInMonth * 24.0f, wxEmptyString, TickData::LARGE)); + m_tickList.push_back(TickData(time + daysVisibleInMonth * 24.0f + m_min_offset * 8760, wxEmptyString, TickData::LARGE)); + int endMonthHours = time + m_min_offset * 8760 + daysVisibleInMonth * 24.0f; //00:00 on first of next month. if (daysVisibleInMonth >= 7) { //Label the month if it has more than seven days visible. +// m_tickList.push_back( +// TickData(time + (daysVisibleInMonth * 24.0f / 2.0f), timeKeeper.Format("%b"), TickData::NONE)); m_tickList.push_back( - TickData(time + (daysVisibleInMonth * 24.0f / 2.0f), timeKeeper.Format("%b"), TickData::NONE)); + TickData(time + (daysVisibleInMonth * 24.0f / 2.0f) + m_min_offset * 8760, timeKeeper.Format("%b"), TickData::NONE)); } timeKeeper2.SetDay(wxDateTime::GetNumberOfDays(timeKeeper2.GetMonth()) / 2); //Middle of the second month. @@ -779,24 +799,27 @@ void wxPLTimeAxis::RecalculateTicksAndLabel() { //Loop, labeling months //While end of month is visible. do { - m_tickList.push_back(TickData(time, timeKeeper2.Format("%b"), TickData::NONE)); +// m_tickList.push_back(TickData(time, timeKeeper2.Format("%b"), TickData::NONE)); + m_tickList.push_back(TickData(time + m_min_offset * 8760, timeKeeper2.Format("%b"), TickData::NONE)); timeKeeper.Set(timeKeeper2.GetTicks()); //timeKeeper is position of last label. timeKeeper2.Add(wxDateSpan::Month()); timeKeeper2.SetDay(1); //timeKeeper2 is day 1 of next month. - m_tickList.push_back(TickData(time + timeKeeper2.Subtract(timeKeeper).GetHours(), wxEmptyString, - TickData::LARGE)); //Adds tick at this pos. (start-month) +// m_tickList.push_back(TickData(time + timeKeeper2.Subtract(timeKeeper).GetHours(), wxEmptyString, +// TickData::LARGE)); //Adds tick at this pos. (start-month) + m_tickList.push_back(TickData(time + timeKeeper2.Subtract(timeKeeper).GetHours() + m_min_offset * 8760, wxEmptyString, + TickData::LARGE)); //Adds tick at this pos. (start-month) timeKeeper2.SetDay(wxDateTime::GetNumberOfDays(timeKeeper2.GetMonth()) / 2); //timeKeeper2 mid month time += timeKeeper2.Subtract(timeKeeper).GetHours(); //hours midMonth. endMonthHours += 24 * wxDateTime::GetNumberOfDays(timeKeeper2.GetMonth()); +// } while (endMonthHours < m_max_scaled); } while (endMonthHours < m_max); //timeKeeper holds the middle of last month we actually labelled. //We still need to label the last month if it has more than 7 days showing. timeKeeper.Add(wxDateSpan::Month()); timeKeeper.SetDay(1); // First not-yet-labeled month - time = endMonthHours - - 24 * wxDateTime::GetNumberOfDays(timeKeeper.GetMonth()); //00:00 on first of not-yet-labeled month. + time = endMonthHours - 24 * wxDateTime::GetNumberOfDays(timeKeeper.GetMonth()); //00:00 on first of not-yet-labeled month. //Take care of fractional days at the max. timeKeeper2 = wxDateTime(01, wxDateTime::Jan, 1970, 00, 00, 00); @@ -808,6 +831,7 @@ void wxPLTimeAxis::RecalculateTicksAndLabel() { time += daysVisibleInMonth * 24.0f; timeKeeper2.Add(wxTimeSpan::Minutes(daysVisibleInMonth * 24.0f * 60.0f)); while (time < m_max && timeKeeper2.GetMonth() == timeKeeper.GetMonth()) { +// while (time < m_max_scaled && timeKeeper2.GetMonth() == timeKeeper.GetMonth()) { daysVisibleInMonth += 1; timeKeeper2.Add(wxTimeSpan::Day()); time += 24; @@ -815,8 +839,8 @@ void wxPLTimeAxis::RecalculateTicksAndLabel() { if (daysVisibleInMonth >= 7) { //Label the month if it has more than seven days visible. - m_tickList.push_back( - TickData(time - (daysVisibleInMonth * 24.0f / 2.0f), timeKeeper.Format("%b"), TickData::NONE)); + m_tickList.push_back(TickData(time - (daysVisibleInMonth * 24.0f / 2.0f), timeKeeper.Format("%b"), TickData::NONE)); +// m_tickList.push_back(TickData(time - (daysVisibleInMonth * 24.0f / 2.0f) + m_min_offset * 8760, timeKeeper.Format("%b third"), TickData::NONE)); } } diff --git a/src/plot/plcolourmap.cpp b/src/plot/plcolourmap.cpp index aaca3044..85af32af 100644 --- a/src/plot/plcolourmap.cpp +++ b/src/plot/plcolourmap.cpp @@ -159,7 +159,7 @@ void wxPLColourMap::Render(wxPLOutputDevice &dc, const wxPLRealRect &geom) { } wxColour wxPLColourMap::ColourForValue(double val) { - if (m_colourList.size() == 0 || !(wxFinite(val))) return *wxBLACK; + if (m_colourList.size() == 0 || !(wxFinite(val))) return *wxCONTOUR_BG; int position = (int) (((double) m_colourList.size()) * ( diff --git a/src/plot/plcontourplot.cpp b/src/plot/plcontourplot.cpp index 0f2c15b5..7769ac00 100644 --- a/src/plot/plcontourplot.cpp +++ b/src/plot/plcontourplot.cpp @@ -143,9 +143,20 @@ void wxPLContourPlot::RebuildContours() { } } } else { - for (size_t k = 0; k < m_levels.size() - 1; k++) { - double zlow = m_levels[k]; - double zhigh = m_levels[k + 1]; + for (size_t k = 0; k < m_levels.size(); k++) { + double zlow = 0; + double zhigh = 0; + if (k == 0) { + zlow = m_levels[k] - (m_levels[1] - m_levels[0]); + zhigh = m_levels[k]; + } + else { + zlow = m_levels[k-1]; + zhigh = m_levels[k]; + } + + //double zlow = m_levels[k]; + //double zhigh = m_levels[k + 1]; std::vector list; qcg.create_filled_contour(zlow, zhigh, list); @@ -250,16 +261,17 @@ void wxPLContourPlot::Draw(wxPLOutputDevice &dc, const wxPLDeviceMapping &map) { dc.NoPen(); // background set to min // assume RebuildMask has been called - wxColor bgc(m_cmap->ColourForValue(m_zMin)); + //wxColor bgc(m_cmap->ColourForValue(m_zMin)); + wxColor bgc(*wxCONTOUR_BG); dc.Brush(bgc); wxRealPoint pos, size; map.GetDeviceExtents(&pos, &size); dc.Rect(pos.x, pos.y, size.x, size.y); // end background - // int ipoly = 0; for (size_t i = 0; i < m_cPolys.size(); i++) { double zmid = 0.5 * (m_cPolys[i].z + m_cPolys[i].zmax); + //double zmid = m_cPolys[i].z; wxColour color(m_cmap->ColourForValue(zmid)); dc.Pen(color, 2); dc.Brush(color); diff --git a/src/plot/pltext.cpp b/src/plot/pltext.cpp index 769e08e7..22818d9a 100644 --- a/src/plot/pltext.cpp +++ b/src/plot/pltext.cpp @@ -890,7 +890,7 @@ wxFreeTypeDraw(wxRealPoint *offset, int ifnt, double points, unsigned int dpi, c } // create image surface of appropriate size - wxSize bounds(std::abs(max.x - min.x), fabs(max.y - min.y)); + wxSize bounds(std::abs(max.x - min.x), std::fabs(max.y - min.y)); wxImage img(bounds, false); // find offset coordinate for top-left placement diff --git a/src/registration.cpp b/src/registration.cpp index 7f723226..5ce936f3 100644 --- a/src/registration.cpp +++ b/src/registration.cpp @@ -42,9 +42,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include +//#include #include +#include + #include static bool gs_enDebug = false; @@ -234,8 +236,8 @@ bool wxOnlineRegistration::CheckInWithServer(int *usage_count) { if (usage_count) *usage_count = -999; - wxJSONValue root; - wxJSONReader reader; +// wxJSONValue root; +// wxJSONReader reader; wxString raw(curl.GetDataAsString()); if (gs_enDebug) { @@ -247,15 +249,18 @@ bool wxOnlineRegistration::CheckInWithServer(int *usage_count) { wxLogStatus("\tresponse: " + raw); } - if (reader.Parse(raw, &root) == 0) { - int code = root.Item("status").AsInt(); + rapidjson::Document reader; + reader.Parse(raw.c_str()); + + if (!reader.HasParseError()) { + int code = reader["status"].GetInt(); if (gs_enDebug) { wxLogStatus("\tcode: %d", code); } if (code == 200) { gs_regData->WriteSetting("count-since-last-verify-" + GetVersionAndPlatform(), wxString::Format("%d", 0)); - if (usage_count) *usage_count = root.Item("result").Item("usage_count").AsInt(); + if (usage_count) *usage_count = reader["result"]["usage_count"].GetInt(); return true; } } @@ -413,11 +418,11 @@ void wxOnlineRegistration::OnRegister(wxCommandEvent &) { wxBusyCursor curs; wxEasyCurl curl(this, wxID_ANY); int code = -1; - wxJSONValue root; - wxJSONReader reader; - + m_output->SetForegroundColour(wxMetroTheme::Colour(wxMT_TEXT)); + rapidjson::Document reader; + if (m_register->GetLabel() == "Resend key") { // https://developer.nrel.gov/api/sam/v1/tracker/resend_key?api_key=SAMAPIKEY&email=someusersemail@somedomain.com wxString url, post; @@ -426,8 +431,10 @@ void wxOnlineRegistration::OnRegister(wxCommandEvent &) { curl.Get(url); wxString raw(curl.GetDataAsString()); - if (reader.Parse(raw, &root) == 0) - code = root.Item("status").AsInt(); + + reader.Parse(raw.c_str()); + if (!reader.HasParseError()) + code = reader["status"].GetInt(); if (gs_enDebug) { wxLogStatus("wxOnlineRegistration::OnRegister (Resend key)"); @@ -453,8 +460,10 @@ void wxOnlineRegistration::OnRegister(wxCommandEvent &) { curl.Get(url); wxString raw(curl.GetDataAsString()); - if (reader.Parse(raw, &root) == 0) - code = root.Item("status").AsInt(); + reader.Parse(raw.c_str()); + + if (!reader.HasParseError()) + code = reader["status"].GetInt(); if (gs_enDebug) { wxLogStatus("wxOnlineRegistration::OnRegister (Resend key)"); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 9246c13c..51816fba 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -75,14 +75,14 @@ endif () if (${CMAKE_PROJECT_NAME} STREQUAL system_advisor_model) target_link_libraries(wexsandbox lk) else () - if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR MSVC) + if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR "Debug" IN_LIST CMAKE_CONFIGURATION_TYPES) unset(LKD_LIB CACHE) find_library(LKD_LIB NAMES lkd.a lkd.lib PATHS $ENV{LKD_LIB} $ENV{LKDIR}/build $ENV{LKDIR}/build/Debug) target_link_libraries(wexsandbox debug ${LKD_LIB}) endif () - if (CMAKE_BUILD_TYPE STREQUAL "Release" OR MSVC) + if (CMAKE_BUILD_TYPE STREQUAL "Release" OR "Release" IN_LIST CMAKE_CONFIGURATION_TYPES) unset(LK_LIB CACHE) find_library(LK_LIB NAMES lk.a lk.lib