From 7ed529af8ffbb8db568b6055f16c4ef3ea8e16b6 Mon Sep 17 00:00:00 2001 From: Hidehisa Akiyama <522630+hidehisaakiyama@users.noreply.github.com> Date: Sat, 23 Mar 2024 20:45:19 +0900 Subject: [PATCH 1/5] Implement a new JSON parser and refactor related code. (#51) * Support the new JSON format. * Support the new json game log format. * Update the rcg parser library to integrate simdjson. --- CMakeLists.txt | 2 +- configure.ac | 6 +- m4/ax_cxx_compile_stdcxx.m4 | 89 +- m4/ax_cxx_compile_stdcxx_17.m4 | 35 + rcss/rcg/CMakeLists.txt | 24 +- rcss/rcg/Makefile.am | 19 +- rcss/rcg/handler.cpp | 203 +- rcss/rcg/handler.h | 249 +- rcss/rcg/parser.cpp | 94 +- rcss/rcg/parser.h | 28 +- rcss/rcg/parser_json.cpp | 705 - rcss/rcg/parser_simdjson.cpp | 646 + rcss/rcg/{parser_json.h => parser_simdjson.h} | 41 +- rcss/rcg/parser_v1.cpp | 140 +- rcss/rcg/parser_v1.h | 39 +- rcss/rcg/parser_v2.cpp | 104 +- rcss/rcg/parser_v2.h | 45 +- rcss/rcg/parser_v3.cpp | 182 +- rcss/rcg/parser_v3.h | 59 +- rcss/rcg/parser_v4.cpp | 721 +- rcss/rcg/parser_v4.h | 57 +- rcss/rcg/simdjson/LICENSE | 201 + rcss/rcg/simdjson/simdjson.cpp | 43725 ++++++++ rcss/rcg/simdjson/simdjson.h | 90327 ++++++++++++++++ rcss/rcg/team_graphic.cpp | 365 - rcss/rcg/team_graphic.h | 144 - rcss/rcg/types.cpp | 2459 +- rcss/rcg/types.h | 1040 +- rcss/rcg/util.cpp | 756 +- rcss/rcg/util.h | 80 +- rcss/rcg/xpm_tile.cpp | 173 - rcss/rcg/xpm_tile.h | 133 - src/CMakeLists.txt | 1 + src/Makefile.am | 2 + src/disp_holder.cpp | 176 +- src/disp_holder.h | 47 +- src/field_canvas.cpp | 16 +- src/main_window.cpp | 18 +- src/player_painter.cpp | 16 +- src/player_type_dialog.cpp | 3 +- src/rcg_handler.cpp | 77 +- src/rcg_handler.h | 39 +- src/team_graphic.cpp | 640 + src/team_graphic.h | 268 + src/team_graphic_painter.cpp | 71 +- src/team_graphic_painter.h | 16 +- 46 files changed, 139524 insertions(+), 4757 deletions(-) create mode 100644 m4/ax_cxx_compile_stdcxx_17.m4 delete mode 100644 rcss/rcg/parser_json.cpp create mode 100644 rcss/rcg/parser_simdjson.cpp rename rcss/rcg/{parser_json.h => parser_simdjson.h} (78%) create mode 100644 rcss/rcg/simdjson/LICENSE create mode 100644 rcss/rcg/simdjson/simdjson.cpp create mode 100644 rcss/rcg/simdjson/simdjson.h delete mode 100644 rcss/rcg/team_graphic.cpp delete mode 100644 rcss/rcg/team_graphic.h delete mode 100644 rcss/rcg/xpm_tile.cpp delete mode 100644 rcss/rcg/xpm_tile.h create mode 100644 src/team_graphic.cpp create mode 100644 src/team_graphic.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b435be5..941f199 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ if(CMAKE_VERSION VERSION_LESS "3.7.0") endif() # compiler options -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) if(NOT CMAKE_BUILD_TYPE) diff --git a/configure.ac b/configure.ac index d9be792..0ea9d15 100644 --- a/configure.ac +++ b/configure.ac @@ -44,7 +44,9 @@ AX_CHECK_ZLIB([], # Checks for header files. ################################################## -AC_CHECK_HEADERS([arpa/inet.h]) +AC_CHECK_HEADERS([arpa/inet.h], + break, + [AC_MSG_ERROR([*** arpa/inet.h not found ***])]) ################################################## # Checks for typedefs, structures, and compiler characteristics. @@ -78,7 +80,7 @@ fi # ---------------------------------------------------------- # check C++ -AX_CXX_COMPILE_STDCXX_14(noext) +AX_CXX_COMPILE_STDCXX_17(noext) # ---------------------------------------------------------- # check boost diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 index 43087b2..8edf515 100644 --- a/m4/ax_cxx_compile_stdcxx.m4 +++ b/m4/ax_cxx_compile_stdcxx.m4 @@ -10,13 +10,13 @@ # # Check for baseline language coverage in the compiler for the specified # version of the C++ standard. If necessary, add switches to CXX and -# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) -# or '14' (for the C++14 standard). +# CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for +# the respective C++ standard version. # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with -# preference for an extended mode. +# preference for no added switch, and then for an extended mode. # # The third argument, if specified 'mandatory' or if left unspecified, # indicates that baseline support for the specified C++ standard is @@ -35,13 +35,15 @@ # Copyright (c) 2015 Moritz Klammler # Copyright (c) 2016, 2018 Krzesimir Nowak # Copyright (c) 2019 Enji Cooper +# Copyright (c) 2020 Jason Merrill +# Copyright (c) 2021 Jörn Heusipp # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 11 +#serial 18 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). @@ -50,6 +52,7 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], [$1], [14], [ax_cxx_compile_alternatives="14 1y"], [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [$1], [20], [ax_cxx_compile_alternatives="20"], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], @@ -62,6 +65,16 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl AC_LANG_PUSH([C++])dnl ac_success=no + m4_if([$2], [], [dnl + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi]) + m4_if([$2], [noext], [], [dnl if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do @@ -91,9 +104,18 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl dnl HP's aCC needs +std=c++11 according to: dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf dnl Cray's crayCC needs "-h std=c++11" + dnl MSVC needs -std:c++NN for C++17 and later (default is C++14) for alternative in ${ax_cxx_compile_alternatives}; do - for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}" MSVC; do + if test x"$switch" = xMSVC; then + dnl AS_TR_SH maps both `:` and `=` to `_` so -std:c++17 would collide + dnl with -std=c++17. We suffix the cache variable name with _MSVC to + dnl avoid this. + switch=-std:c++${alternative} + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_${switch}_MSVC]) + else + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + fi AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" @@ -140,7 +162,6 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 ) - dnl Test body for checking C++14 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], @@ -148,12 +169,24 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 ) +dnl Test body for checking C++17 support + m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 ) +dnl Test body for checking C++20 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 +) + + dnl Tests for new features in C++11 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ @@ -165,7 +198,11 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ #error "This is not a C++ compiler" -#elif __cplusplus < 201103L +// MSVC always sets __cplusplus to 199711L in older versions; newer versions +// only set it correctly if /Zc:__cplusplus is specified as well as a +// /std:c++NN switch: +// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ +#elif __cplusplus < 201103L && !defined _MSC_VER #error "This is not a C++11 compiler" @@ -456,7 +493,7 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ #error "This is not a C++ compiler" -#elif __cplusplus < 201402L +#elif __cplusplus < 201402L && !defined _MSC_VER #error "This is not a C++14 compiler" @@ -580,7 +617,7 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ #error "This is not a C++ compiler" -#elif __cplusplus < 201703L +#elif __cplusplus < 201703L && !defined _MSC_VER #error "This is not a C++17 compiler" @@ -946,6 +983,36 @@ namespace cxx17 } // namespace cxx17 -#endif // __cplusplus < 201703L +#endif // __cplusplus < 201703L && !defined _MSC_VER + +]]) + + +dnl Tests for new features in C++20 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 202002L && !defined _MSC_VER + +#error "This is not a C++20 compiler" + +#else + +#include + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // __cplusplus < 202002L && !defined _MSC_VER ]]) diff --git a/m4/ax_cxx_compile_stdcxx_17.m4 b/m4/ax_cxx_compile_stdcxx_17.m4 new file mode 100644 index 0000000..a683417 --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx_17.m4 @@ -0,0 +1,35 @@ +# ============================================================================= +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_17.html +# ============================================================================= +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX_17([ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the C++17 +# standard; if necessary, add switches to CXX and CXXCPP to enable +# support. +# +# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX +# macro with the version set to C++17. The two optional arguments are +# forwarded literally as the second and third argument respectively. +# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for +# more information. If you want to use this macro, you also need to +# download the ax_cxx_compile_stdcxx.m4 file. +# +# LICENSE +# +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016 Krzesimir Nowak +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 2 + +AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) +AC_DEFUN([AX_CXX_COMPILE_STDCXX_17], [AX_CXX_COMPILE_STDCXX([17], [$1], [$2])]) diff --git a/rcss/rcg/CMakeLists.txt b/rcss/rcg/CMakeLists.txt index 10a8ee2..dd533cf 100644 --- a/rcss/rcg/CMakeLists.txt +++ b/rcss/rcg/CMakeLists.txt @@ -1,16 +1,15 @@ add_library(rcssrcg SHARED - handler.cpp - parser.cpp - parser_v1.cpp - parser_v2.cpp - parser_v3.cpp - parser_v4.cpp - parser_json.cpp - util.cpp - types.cpp - team_graphic.cpp - xpm_tile.cpp + simdjson/simdjson.cpp + handler.cpp + parser.cpp + parser_v1.cpp + parser_v2.cpp + parser_v3.cpp + parser_v4.cpp + parser_simdjson.cpp + util.cpp + types.cpp ) target_include_directories(rcssrcg @@ -28,7 +27,7 @@ target_compile_options(rcssrcg set_target_properties(rcssrcg PROPERTIES - VERSION 18.0.0 + VERSION 19.0.0 SOVERSION 18 ) @@ -45,6 +44,7 @@ install(FILES parser_v2.h parser_v3.h parser_v4.h + parser_simdjson.h types.h util.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rcss/rcg diff --git a/rcss/rcg/Makefile.am b/rcss/rcg/Makefile.am index 789ed64..c62bd84 100644 --- a/rcss/rcg/Makefile.am +++ b/rcss/rcg/Makefile.am @@ -1,19 +1,20 @@ ## Process this file with automake to produce Makefile.in +AUTOMAKE_OPTIONS = subdir-objects + lib_LTLIBRARIES = librcssrcg.la librcssrcg_la_SOURCES = \ + simdjson/simdjson.cpp \ handler.cpp \ parser.cpp \ parser_v1.cpp \ parser_v2.cpp \ parser_v3.cpp \ parser_v4.cpp \ - parser_json.cpp \ + parser_simdjson.cpp \ types.cpp \ - util.cpp \ - xpm_tile.cpp \ - team_graphic.cpp + util.cpp librcssrcgincludedir = $(includedir)/rcss/rcg @@ -25,16 +26,14 @@ librcssrcginclude_HEADERS = \ parser_v2.h \ parser_v3.h \ parser_v4.h \ - parser_json.h \ + parser_simdjson.h \ types.h \ - util.h \ - xpm_tile.h \ - team_graphic.h + util.h noinst_HEADERS = \ - nlohmann/json.hpp + simdjson/simdjson.h -librcssrcg_la_LDFLAGS = -version-info 17:0:0 +librcssrcg_la_LDFLAGS = -version-info 19:0:0 #libXXXX_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) # 1. Start with version information of `0:0:0' for each libtool library. # diff --git a/rcss/rcg/handler.cpp b/rcss/rcg/handler.cpp index 3c4f535..2c4b8b0 100644 --- a/rcss/rcg/handler.cpp +++ b/rcss/rcg/handler.cpp @@ -37,8 +37,8 @@ #include "util.h" -#ifdef HAVE_NETINET_IN_H -#include +#ifdef HAVE_ARPA_INET_H +#include #endif #ifdef HAVE_WINDOWS_H #include @@ -54,7 +54,8 @@ namespace rcg { */ Handler::Handler() - : M_log_version( 0 ) + : M_log_version( 0 ), + M_read_time( 0 ) { } @@ -68,5 +69,201 @@ Handler::~Handler() } +/*-------------------------------------------------------------------*/ +/*! + +*/ +bool +Handler::handleDispInfo( const dispinfo_t & dinfo ) +{ + handleLogVersion( REC_VERSION_2 ); + + switch ( ntohs( dinfo.mode ) ) { + case SHOW_MODE: + return handleShowInfo( dinfo.body.show ); + break; + case MSG_MODE: + return handleMsg( M_read_time, + ntohs( dinfo.body.msg.board ), + std::string( dinfo.body.msg.message ) ); + break; + case DRAW_MODE: + return handleDrawInfo( dinfo.body.draw ); + break; + default: + std::cerr << __FILE__ << ':' << __LINE__ + << " detect unsupported mode [" + << static_cast< int >( ntohs( dinfo.mode ) ) << ']' + << std::endl; + break; + } + return false; +} + +/*-------------------------------------------------------------------*/ +/*! + +*/ +bool +Handler::handleDispInfo2( const dispinfo_t2 & dinfo2 ) +{ + handleLogVersion( REC_VERSION_3 ); + + switch ( ntohs( dinfo2.mode ) ) { + case SHOW_MODE: + return handleShowInfo2( dinfo2.body.show ); + break; + case MSG_MODE: + return handleMsg( M_read_time, + ntohs( dinfo2.body.msg.board ), + std::string( dinfo2.body.msg.message ) ); + break; + case PT_MODE: + return handlePlayerType( dinfo2.body.ptinfo ); + break; + case PARAM_MODE: + return handleServerParam( dinfo2.body.sparams ); + break; + case PPARAM_MODE: + return handlePlayerParam( dinfo2.body.pparams ); + break; + default: + std::cerr << __FILE__ << ':' << __LINE__ + << " detect unsupported mode [" + << static_cast< int >( ntohs( dinfo2.mode ) ) << ']' + << std::endl; + break; + } + return false; +} + +/*-------------------------------------------------------------------*/ +/*! + +*/ +bool +Handler::handleShowInfo( const showinfo_t & info ) +{ + ShowInfoT show; + convert( info, show ); + + M_read_time = static_cast< int >( show.time_ ); + + return ( handlePlayMode( info.pmode ) + && handleTeamInfo( info.team[0], info.team[1] ) + && handleShow( show ) ); +} + +/*-------------------------------------------------------------------*/ +/*! + +*/ +bool +Handler::handleShowInfo2( const showinfo_t2 & info ) +{ + ShowInfoT show; + convert( info, show ); + M_read_time = static_cast< int >( show.time_ ); + + return ( handlePlayMode( info.pmode ) + && handleTeamInfo( info.team[0], info.team[1] ) + && handleShow( show ) ); +} + +/*-------------------------------------------------------------------*/ +/*! + +*/ +bool +Handler::handleShortShowInfo2( const short_showinfo_t2 & info ) +{ + ShowInfoT show; + convert( info, show ); + + M_read_time = static_cast< int >( show.time_ ); + + return handleShow( show ); +} + +/*-------------------------------------------------------------------*/ +/*! + +*/ +bool +Handler::handleMsgInfo( const Int16 board, + const std::string & msg ) +{ + return handleMsg( M_read_time, board, msg ); +} + +/*-------------------------------------------------------------------*/ +/*! + +*/ +bool +Handler::handleDrawInfo( const drawinfo_t & draw ) +{ + return handleDraw( M_read_time, draw ); +} + +/*-------------------------------------------------------------------*/ +/*! + +*/ +bool +Handler::handlePlayMode( char playmode ) +{ + return handlePlayMode( M_read_time, static_cast< PlayMode >( playmode ) ); +} + +/*-------------------------------------------------------------------*/ +/*! + +*/ +bool +Handler::handleTeamInfo( const team_t & team_left, + const team_t & team_right ) +{ + return handleTeam( M_read_time, TeamT( team_left ), TeamT( team_right ) ); +} + +/*-------------------------------------------------------------------*/ +/*! + +*/ +bool +Handler::handlePlayerType( const player_type_t & type ) +{ + return handlePlayerType( PlayerTypeT( type ) ); +} + +/*-------------------------------------------------------------------*/ +/*! + +*/ +bool +Handler::handleServerParam( const server_params_t & param ) +{ + return handleServerParam( ServerParamT( param ) ); +} + +/*-------------------------------------------------------------------*/ +/*! + +*/ +bool +Handler::handlePlayerParam( const player_params_t & param ) +{ + return handlePlayerParam( PlayerParamT( param ) ); +} + +/*-------------------------------------------------------------------*/ +bool +Handler::handlePlayMode( const int time, + const std::string & playmode ) +{ + return handlePlayMode( time, to_playmode_enum( playmode ) ); +} + } // end namespace } // end namespace diff --git a/rcss/rcg/handler.h b/rcss/rcg/handler.h index a894d81..fda22f4 100644 --- a/rcss/rcg/handler.h +++ b/rcss/rcg/handler.h @@ -35,13 +35,11 @@ #include #include -#include +#include namespace rcss { namespace rcg { -class XpmTile; - /*! \class Handler \brief abstract rcg data handler class. @@ -51,9 +49,17 @@ class XpmTile; class Handler { private: - //! RCG version number(1-3, default:0) + //! RCG version number int M_log_version; + //! server version (available only in json) + std::string M_server_version; + //! timestamp (available only in json) + std::string M_timestamp; + + //! last handled game time + int M_read_time; + protected: /*! @@ -97,42 +103,159 @@ class Handler { } /*! - \brief (pure virtual) handle end of file + \brief update the server version information + \param version string \return result status - */ + */ virtual - bool handleEOF() = 0; + bool handleServerVersion( const std::string & version ) + { + M_server_version = version; + return true; + } /*! - \brief (pure virtual) handle the start of show info v4 - \param time game time of handled show info - \param show read data + \brief get the server version string + \return server version string + */ + const std::string & serverVersion() const + { + return M_server_version; + } + + /*! + \brief update the time stamp information + \param timestamp string \return result status */ - virtual - bool handleShow( const ShowInfoT & show ) = 0; + bool handleTimestamp( const std::string & timestamp ) + { + M_timestamp = timestamp; + return true; + } + + /*! + \brief get the time stamp string + \return time stamp string + */ + const std::string & timestamp() const + { + return M_timestamp; + } + + // + // old version handers + // all data are automatically converted to the intermediate format. + // + + /*! + \brief handle dispinfo_t. + \param info new data + \return result status + */ + bool handleDispInfo( const dispinfo_t & info ); + + /*! + \brief handle dispinfo_t2. + \param info new data + \return result status + */ + bool handleDispInfo2( const dispinfo_t2 & info ); + + /*! + \brief handle showinfo_t + \param info handled data + \return result status + */ + bool handleShowInfo( const showinfo_t & info ); + + /*! + \brief handle showinfo_t2 + \param info handled data + \return result status + */ + bool handleShowInfo2( const showinfo_t2 & info ); + + /*! + \brief handle short_showinfo_t. + \param info handled data + \return result status + */ + bool handleShortShowInfo2( const short_showinfo_t2 & info ); + + /*! + \brief handle msginfo_t + \param board handled message type + \param msg handled message data + \return result status + */ + bool handleMsgInfo( const Int16 board, + const std::string & msg ); + + /*! + \brief handle drawinfo_t + \param draw new data + \return result status + */ + bool handleDrawInfo( const drawinfo_t & draw ); /*! \brief handle playmode - \param time game time of handled playmode info - \param pm playmode id + \param playmode handled playmode character \return result status - */ - virtual - bool handlePlayMode( const int time, - const PlayMode pm ) = 0; + */ + bool handlePlayMode( char playmode ); /*! - \brief handle team info - \param time game time of handled team info - \param team_l left team info - \param team_r right team info + \brief handle team data + \param team_l left team data + \param team_r right team data + \return result status + */ + bool handleTeamInfo( const team_t & team_l, + const team_t & team_r ); + + /*! + \brief handle player_type_t + \param type binary data + \return result status + */ + bool handlePlayerType( const player_type_t & type ); + + /*! + \brief handle server_params_t + \param param binary data + \return result status + */ + bool handleServerParam( const server_params_t & param ); + + /*! + \brief handle player_params_t + \param param binary data + \return result status + */ + bool handlePlayerParam( const player_params_t & param ); + + /*! + \brief (pure virtual) handle end of file \return result status */ virtual - bool handleTeam( const int time, - const TeamT & team_l, - const TeamT & team_r ) = 0; + bool handleEOF() = 0; + + + // + // version 4, 5 + // + + /*! + \brief (pure virtual) handle the start of show info v4 + \param time game time of handled show info + \param show read data + \return result status + */ + virtual + bool handleShow( const ShowInfoT & show ) = 0; /*! \brief (pure virtual) handle msg info @@ -147,75 +270,83 @@ class Handler { const std::string & msg ) = 0; /*! - \brief (pure virtual) handle draw clear - \param time game time + \brief (pure virtual) handle draw info + \param time game time of handled data + \param draw new data \return result status */ virtual - bool handleDrawClear( const int time ) = 0; + bool handleDraw( const int time, + const drawinfo_t & draw ) = 0; /*! - \brief (pure virtual) handle draw point - \param time game time - \param point point information - \return result status - */ - virtual - bool handleDrawPoint( const int time, - const PointT & point ) = 0; - - /*! - \brief (pure virtual) handle draw circle - \param time game time - \param circle circle information + \brief handle playmode + \param time game time of handled playmode info + \param pm playmode id \return result status */ virtual - bool handleDrawCircle( const int time, - const CircleT & circle ) = 0; + bool handlePlayMode( const int time, + const PlayMode pm ) = 0; /*! - \brief (pure virtual) handle draw circle - \param time game time - \param line line information + \brief handle team info + \param time game time of handled team info + \param team_l left team info + \param team_r right team info \return result status - */ + */ virtual - bool handleDrawLine( const int time, - const LineT & line ) = 0; + bool handleTeam( const int time, + const TeamT & team_l, + const TeamT & team_r ) = 0; /*! \brief handle server_param message - \param msg raw message string + \param param parameter holder \return result status */ virtual - bool handleServerParam( const ServerParamT & sparam ) = 0; + bool handleServerParam( const ServerParamT & param ) = 0; /*! \brief handle player_param message - \param msg raw message string + \param param parameter holder \return result status */ virtual - bool handlePlayerParam( const PlayerParamT & pparam ) = 0; + bool handlePlayerParam( const PlayerParamT & param ) = 0; /*! \brief handle player_type message - \param msg raw message string + \param param parameter holder \return result status */ virtual - bool handlePlayerType( const PlayerTypeT & ptype ) = 0; + bool handlePlayerType( const PlayerTypeT & param ) = 0; /*! - \brief handle XPM tile of TeamGraphic - */ + \brief handle team_graphic message + \param msg raw message string + \return result status + */ virtual - bool handleTeamGraphic( const Side side, + bool handleTeamGraphic( const char side, const int x, const int y, - std::shared_ptr< XpmTile > tile ) = 0; + const std::vector< std::string > & xpm_data ) = 0; + + // + // + // + + /*! + \brief wrapper of handlePlayMode(int,PlayMode) + \param playmode playmode name + \return result status + */ + bool handlePlayMode( const int time, + const std::string & playmode ); }; diff --git a/rcss/rcg/parser.cpp b/rcss/rcg/parser.cpp index bd9a438..ead5787 100644 --- a/rcss/rcg/parser.cpp +++ b/rcss/rcg/parser.cpp @@ -41,25 +41,14 @@ #include "parser_v2.h" #include "parser_v3.h" #include "parser_v4.h" -#include "parser_json.h" +#include "parser_simdjson.h" #include +#include namespace rcss { namespace rcg { -/*-------------------------------------------------------------------*/ -/*! - -*/ -// Parser::Creators & -// Parser::creators() -// { -// static Creators s_instance; -// return s_instance; -// } - - /*-------------------------------------------------------------------*/ /*! @@ -67,8 +56,6 @@ namespace rcg { Parser::Ptr Parser::create( std::istream & is ) { - Parser::Ptr ptr; - char header[5]; int version = REC_OLD_VERSION; @@ -76,62 +63,87 @@ Parser::create( std::istream & is ) if ( is.gcount() != 4 ) { - return ptr; + std::cerr << "(rcss::rcg::Parser::create) no header." << std::endl; + return Parser::Ptr(); } - if ( header[0] == 'J' - && header[1] == 'S' - && header[2] == 'O' - && header[3] == 'N' ) + if ( header[0] == '[' ) { - std::cerr << "(rcss::rcg::Parser::create) game log version = json" << std::endl; - ptr = Parser::Ptr( new ParserJSON() ); - return ptr; + version = REC_VERSION_JSON; } - - - if ( header[0] == 'U' - && header[1] == 'L' - && header[2] == 'G' ) + else if ( header[0] == 'U' + && header[1] == 'L' + && header[2] == 'G' ) { version = static_cast< int >( header[3] ); } + std::cerr << "(rcss::rcg::Parser::create) rcg version = "; + if ( version == -1 ) + { + std::cerr << "json"; + } + else + { + std::cerr << ( version == static_cast< int >( '0' ) + REC_VERSION_6 ? REC_VERSION_6 + : version == static_cast< int >( '0' ) + REC_VERSION_5 ? REC_VERSION_5 + : version == static_cast< int >( '0' ) + REC_VERSION_4 ? REC_VERSION_4 + : version ); + } + std::cerr << std::endl; + + Parser::Ptr ptr; + if ( version == static_cast< int >( '0' ) + REC_VERSION_6 ) { - // ParserV4 can parse the v6 format. - std::cerr << "(rcss::rcg::Parser::crete) game log version = " << REC_VERSION_6 << std::endl; - ptr = Parser::Ptr( new rcss::rcg::ParserV4() ); + ptr = Parser::Ptr( new ParserV4() ); } else if ( version == static_cast< int >( '0' ) + REC_VERSION_5 ) { - // ParserV4 can parse the v5 format. - std::cerr << "(rcss::rcg::Parser::crete) game log version = " << REC_VERSION_5 << std::endl; - ptr = Parser::Ptr( new rcss::rcg::ParserV4() ); + ptr = Parser::Ptr( new ParserV4() ); } else if ( version == static_cast< int >( '0' ) + REC_VERSION_4 ) { - std::cerr << "(rcss::rcg::Parser::create) game log version = " << REC_VERSION_4 << std::endl; - ptr = Parser::Ptr( new rcss::rcg::ParserV4() ); + ptr = Parser::Ptr( new ParserV4() ); } else if ( version == REC_VERSION_3 ) { - std::cerr << "(rcss::rcg::Parser::create) game log version = " << version << std::endl; - ptr = Parser::Ptr( new rcss::rcg::ParserV3() ); + ptr = Parser::Ptr( new ParserV3() ); } else if ( version == REC_VERSION_2 ) { - std::cerr << "(rcss::rcg::Parser::create) game log version = " << version << std::endl; - ptr = Parser::Ptr( new rcss::rcg::ParserV2() ); + ptr = Parser::Ptr( new ParserV2() ); } else if ( version == REC_OLD_VERSION ) { - std::cerr << "(rcss::rcg::Parser::create) game log version = " << version << std::endl; ptr = Parser::Ptr( new ParserV1() ); } + else if ( version == REC_VERSION_JSON ) + { + ptr = Parser::Ptr( new ParserSimdJSON() ); + } + else + { + std::cerr << "(rcss::rcg::Parser::create) Unsupported version." << std::endl; + } return ptr; } + +bool +Parser::parse( const std::string & filepath, + Handler & handler ) const +{ + std::ifstream fin( filepath ); + if ( ! fin ) + { + return false; + } + + return parse( fin, handler ); +} + + } } diff --git a/rcss/rcg/parser.h b/rcss/rcg/parser.h index 4cdaadc..e622867 100644 --- a/rcss/rcg/parser.h +++ b/rcss/rcg/parser.h @@ -50,15 +50,7 @@ class Parser { public: typedef std::shared_ptr< Parser > Ptr; //!< rcg parser pointer type - // typedef Ptr (*Creator)(); //!< rcg parser creator function - // typedef Factory< Creator, int > Creators; //!< creator function holder - - // /*! - // \brief factory holder singleton - // \return reference to the factory holder instance - // */ - // static - // Creators & creators(); + typedef Ptr (*Creator)(); //!< rcg parser creator function /*! \brief create a suitable version parser instance depending on the input stream. @@ -66,7 +58,7 @@ class Parser { \return smart pointer to the rcg parser instance poionted index of istream becomes 4. - */ + */ static Ptr create( std::istream & is ); @@ -74,7 +66,7 @@ class Parser { /*! \brief constructor is accessible only from the derived classes. - */ + */ Parser() = default; public: @@ -84,25 +76,29 @@ class Parser { */ virtual ~Parser() - { } + { } /*! \brief (pure virtual) get log version \return version number - */ + */ virtual int version() const = 0; /*! \brief (pure virtual) analyze log data from input stream - \param is input stream + \param is reference to the imput stream (usually ifstream/gzifstream). \param handler reference to the rcg data handler. \retval true, if successfuly parsed. \retval false, if incorrect format is detected. - */ + */ virtual bool parse( std::istream & is, - Handler & handler ) = 0; + Handler & handler ) const = 0; + + virtual + bool parse( const std::string & filepath, + Handler & handler ) const; }; } // end of namespace diff --git a/rcss/rcg/parser_json.cpp b/rcss/rcg/parser_json.cpp deleted file mode 100644 index 06ca9bc..0000000 --- a/rcss/rcg/parser_json.cpp +++ /dev/null @@ -1,705 +0,0 @@ -// -*-c++-*- - -/*! - \file parser_json.cpp - \brief rcg v6 (JSON format) parser Source File. -*/ - -/* - *Copyright: - - Copyright (C) Hidehisa AKIYAMA - - This code is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - *EndCopyright: - */ - -///////////////////////////////////////////////////////////////////// - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "parser_json.h" - -#include "handler.h" -#include "types.h" -#include "xpm_tile.h" - -#include "nlohmann/json.hpp" - -#include -#include -#include - -namespace rcss { -namespace rcg { - -struct ParserJSON::Impl { - - typedef std::function< bool( const nlohmann::json & data, Handler & handler ) > Func; - - std::unordered_map< std::string, Func > funcs_; - - Impl(); - - bool parseData( const nlohmann::json & data, - Handler & hander ); - - bool parseHeader( const nlohmann::json & data, - Handler & handler ); - - bool parseShow( const nlohmann::json & data, - Handler & handler ); - bool setBall( const nlohmann::json & data, - ShowInfoT & show ); - bool setPlayers( const nlohmann::json & data, - ShowInfoT & show ); - bool setPlayer( const nlohmann::json & player, - ShowInfoT & show ); - - bool parsePlayMode( const nlohmann::json & data, - Handler & handler ); - PlayMode getPlayModeId( const std::string & pmode_str ); - - bool parseTeam( const nlohmann::json & data, - Handler & handler ); - bool setTeams( const nlohmann::json & teams, - TeamT & team_l, - TeamT & team_r ); - - bool parseMsg( const nlohmann::json & data, - Handler & handler ); - bool parseTeamGraphic( const nlohmann::json & data, - Handler & handler ); - - bool parseServerParam( const nlohmann::json & data, - Handler & handler ); - bool parsePlayerParam( const nlohmann::json & data, - Handler & handler ); - bool parsePlayerType( const nlohmann::json & data, - Handler & handler ); - - Side toSide( const std::string & str ) - { - return ( str == "l" - ? LEFT - : str == "r" - ? RIGHT - : NEUTRAL ); - } -}; - - -/*-------------------------------------------------------------------*/ -ParserJSON::Impl::Impl() -{ - using std::placeholders::_1; - using std::placeholders::_2; - - funcs_["show"] = std::bind( &Impl::parseShow, this, _1, _2 ); - funcs_["playmode"] = std::bind( &Impl::parsePlayMode, this, _1, _2 ); - funcs_["team"] = std::bind( &Impl::parseTeam, this, _1, _2 ); - funcs_["msg"] = std::bind( &Impl::parseMsg, this, _1, _2 ); - - funcs_["team_graphic"] = std::bind( &Impl::parseTeamGraphic, this, _1, _2 ); - - funcs_["server_param"] = std::bind( &Impl::parseServerParam, this, _1, _2 ); - funcs_["player_param"] = std::bind( &Impl::parsePlayerParam, this, _1, _2 ); - funcs_["player_type"] = std::bind( &Impl::parsePlayerType, this, _1, _2 ); - - funcs_["header"] = std::bind( &Impl::parseHeader, this, _1, _2 ); -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::parseData( const nlohmann::json & data, - Handler & handler ) -{ - if ( ! data.contains( "type" ) ) - { - return false; - } - - std::unordered_map< std::string, Func >::iterator it = funcs_.find( data.at( "type" ) ); - if ( it == funcs_.end() ) - { - return false; - } - - return it->second( data, handler ); -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::parseHeader( const nlohmann::json & /*data*/, - Handler & /*handler*/ ) -{ - return true; -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::parseShow( const nlohmann::json & data, - Handler & handler ) -{ - int time, stime; - - try - { - time = data.at( "time" ); - stime = ( data.contains( "stime" ) ? data.at( "stime" ).get< int >() : 0 ); - } - catch ( std::exception & e ) - { - std::cerr << "(rcss::rcg::ParserJSON::Impl::parseShow) Illegal elment in show data.\n" - << e.what() << std::endl; - return false; - } - - ShowInfoT show; - - show.time_ = time; - show.stime_ = stime; - - if ( data.contains( "mode" ) ) - { - PlayMode pm = getPlayModeId( data.at( "mode" ) ); - if ( ! handler.handlePlayMode( time, pm ) ) - { - return false; - } - } - - if ( data.contains( "teams" ) ) - { - TeamT team_l, team_r; - setTeams( data.at( "teams" ), team_l, team_r ); - if ( ! handler.handleTeam( time, team_l, team_r ) ) - { - return false; - } - } - - if ( ! data.contains( "ball" ) - || ! setBall( data, show ) ) - { - return false; - } - - if ( ! data.contains( "players" ) - || ! setPlayers( data, show ) ) - { - return false; - } - - //return handler.handleShow( time, stime, show ); - return handler.handleShow( show ); -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::setBall( const nlohmann::json & data, - ShowInfoT & show ) -{ - try - { - const nlohmann::json & ball = data.at( "ball" ); - show.ball_.x_ = ball.at( "x" ); - show.ball_.y_ = ball.at( "y" ); - show.ball_.vx_ = ball.at( "vx" ); - show.ball_.vy_ = ball.at( "vx" ); - } - catch ( std::exception & e ) - { - std::cerr << "(rcss::rcg::ParserJSON::Impl::setBall) Illegal element in ball data.\n" - << e.what() << std::endl; - return false; - } - - return true; -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::setPlayers( const nlohmann::json & data, - ShowInfoT & show ) -{ - try - { - const nlohmann::json & player_array = data.at( "players" ); - if ( ! player_array.is_array() ) - { - std::cerr << "(rcss::rcg::ParserJSON::Impl::setPlayers) No array in players data." << std::endl; - return false; - } - - for ( const nlohmann::json & p : player_array ) - { - if ( ! setPlayer( p, show ) ) - { - return false; - } - } - } - catch ( std::exception & e ) - { - return false; - } - - return true; -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::setPlayer( const nlohmann::json & player, - ShowInfoT & show ) -{ - try - { - const Side side = toSide( player.at( "side" ) ); - const int unum = player.at( "unum" ); - - if ( side == NEUTRAL ) - { - std::cerr << "(rcss::rcg::ParserJSON::Impl::setPlayer) Illegal side " - << player.at( "side" ) << " in player data." << std::endl; - return false; - } - - if ( unum < 1 || MAX_PLAYER < unum ) - { - std::cerr << "(rcss::rcg::ParserJSON::Impl::setPlayer) Illegal unum " << unum - << " in player data." << std::endl; - return false; - } - - PlayerT * p = ( side == LEFT - ? &show.players_[unum-1] - : &show.players_[MAX_PLAYER+unum-1] ); - - p->side_ = side; - p->unum_ = unum; - p->type_ = player.at( "type" ); - - p->high_quality_ = ( player.at( "vq" ) == "h" ? true : false ); - - if ( player.contains( "fside" ) ) p->focus_side_ = toSide( player.at( "fside" ) ); - if ( player.contains( "fnum" ) ) p->focus_unum_ = player.at( "fnum" ); - - p->state_ = player.at( "state" ); - - p->x_ = player.at( "x" ); - p->y_ = player.at( "y" ); - p->vx_ = player.at( "vx" ); - p->vy_ = player.at( "vy" ); - p->body_ = player.at( "body" ); - p->neck_ = player.at( "neck" ); - if ( player.contains( "px" ) ) p->point_x_ = player.at( "px" ); - if ( player.contains( "py" ) ) p->point_y_ = player.at( "py" ); - - p->view_width_ = player.at( "vw" ); - - if ( player.contains( "fdist" ) ) p->focus_dist_ = player.at( "fdist" ); - if ( player.contains( "fdir" ) ) p->focus_dir_ = player.at( "fdir" ); - - p->stamina_ = player.at( "stamina" ); - p->effort_ = player.at( "effort" ); - p->recovery_ = player.at( "recovery" ); - p->stamina_capacity_ = player.at( "capacity" ); - - if ( player.contains( "count" ) ) - { - const nlohmann::json & counts = player.at( "count" ); - p->kick_count_ = counts.at( "kick" ); - p->dash_count_ = counts.at( "dash" ); - p->turn_count_ = counts.at( "turn" ); - p->catch_count_= counts.at( "catch" ); - p->move_count_ = counts.at( "move" ); - p->turn_neck_count_ = counts.at( "turn_neck" ); - p->change_view_count_ = counts.at( "change_view" ); - p->say_count_ = counts.at( "say" ); - p->tackle_count_ = counts.at( "tackle" ); - p->pointto_count_ = counts.at( "pointto" ); - p->attentionto_count_ = counts.at( "attentionto" ); - if ( counts.contains( "change_focus" ) ) p->change_focus_count_ = counts.at( "change_focus" ); - } - } - catch ( std::exception & e ) - { - std::cerr << "(rcss::rcg::ParserJSON::Impl::setPlayer) Illegal element in player data.\n" - << e.what() << std::endl; - return false; - } - - return true; -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::parsePlayMode( const nlohmann::json & data, - Handler & handler ) -{ - int time = 0; - // int stime = 0; - std::string playmode; - - try - { - time = data.at( "time" ); - // stime = ( data.contains( "stime" ) - // ? data.at( "stime" ) - // : 0 ); - playmode = data.at( "mode" ); - } - catch ( std::exception & e ) - { - std::cerr << "(rcss::rcg::ParserJSON::Impl::parsePlayMode) Illegal element in playmode data.\n" - << e.what() << std::endl; - return false; - } - - PlayMode pm = getPlayModeId( data.at( "mode" ) ); - return handler.handlePlayMode( time, pm ); -} - -/*-------------------------------------------------------------------*/ -PlayMode -ParserJSON::Impl::getPlayModeId( const std::string & pmode_str ) -{ - static const char * playmode_strings[] = PLAYMODE_STRINGS; - - PlayMode pm = PM_Null; - for ( int n = 0; n < PM_MAX; ++n ) - { - if ( pmode_str == playmode_strings[n] ) - { - pm = static_cast< PlayMode >( n ); - break; - } - } - - return pm; -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::parseTeam( const nlohmann::json & data, - Handler & handler ) -{ - int time; - TeamT team_l, team_r; - try - { - time = data.at( "time" ); - const nlohmann::json & teams = data.at( "teams" ); - if ( ! setTeams( teams, team_l, team_r ) ) - { - return false; - } - } - catch ( std::exception & e ) - { - std::cerr << "(rcss::rcg::ParserJSON::Impl::parseTeam) Illegal element in team data.\n" - << e.what() << std::endl; - return false; - } - - - return handler.handleTeam( time, team_l, team_r ); -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::setTeams( const nlohmann::json & teams, - TeamT & team_l, - TeamT & team_r ) -{ - if ( ! teams.is_array() ) - { - std::cerr << "(rcss::rcg::ParserJSON::Impl::setTeams) No array in team data." << std::endl; - return false; - } - - try - { - const nlohmann::json & data_l = teams.at( 0 ); - const nlohmann::json & data_r = teams.at( 1 ); - - team_l.name_ = data_l.at( "name" ).is_null() ? "null" : data_l.at( "name" ); - team_l.score_ = data_l.at( "score" ); - if ( data_l.contains( "pen_score" ) ) team_l.pen_score_ = data_l.at( "pen_score" ); - if ( data_l.contains( "pen_miss" ) ) team_l.pen_miss_ = data_l.at( "pen_miss" ); - - team_r.name_ = data_r.at( "name" ).is_null() ? "null" : data_r.at( "name" ); - team_r.score_ = data_r.at( "score" ); - if ( data_r.contains( "pen_score" ) ) team_r.pen_score_ = data_r.at( "pen_score" ); - if ( data_r.contains( "pen_miss" ) ) team_r.pen_miss_ = data_r.at( "pen_miss" ); - } - catch ( std::exception & e ) - { - std::cerr << "(rcss::rcg::ParserJSON::Impl::setTeams) Illegal data in team array.\n" - << e.what() << std::endl; - return false; - } - - return true; -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::parseMsg( const nlohmann::json & data, - Handler & handler ) -{ - try - { - return handler.handleMsg( data.at( "time" ), - data.at( "board" ), - data.at( "message" ) ); - } - catch ( std::exception & e ) - { - std::cerr << "(rcss::rcg::ParserJSON::Impl::parseMsg) Illegal elment in msg data.\n" - << e.what() << std::endl; - } - - return false; -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::parseTeamGraphic( const nlohmann::json & data, - Handler & handler ) -{ - try - { - std::shared_ptr< XpmTile > tile( new XpmTile() ); - - const std::string side_str = data.at( "side" ); - const Side side = ( side_str == "l" ? LEFT : - side_str == "r" ? RIGHT : - NEUTRAL ); - - const int x = data.at( "x" ); - const int y = data.at( "y" ); - - //for ( const nlohmann::json & str : data.at( "xpm" ) ) - for ( const std::string & str : data.at( "xpm" ) ) - { - if ( ! tile->addData( str.c_str() ) ) - { - return false; - } - } - - return handler.handleTeamGraphic( side, x, y, tile ); - } - catch ( std::exception & e ) - { - std::cerr << "(rcss::rcg::ParserJSON::Impl::parseMsg) Illegal elment in team_graphic data.\n" - << e.what() << std::endl; - } - - return true; -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::parseServerParam( const nlohmann::json & data, - Handler & handler ) -{ - ServerParamT server_param; - for ( const auto & param : data.at( "params" ).items() ) - { - if ( param.value().is_number_integer() ) - { - server_param.setInt( param.key(), param.value().get< int >() ); - } - else if ( param.value().is_number() ) - { - server_param.setDouble( param.key(), param.value().get< double >() ); - } - else if ( param.value().is_boolean() ) - { - server_param.setBool( param.key(), param.value().get< bool >() ); - } - else if ( param.value().is_string() ) - { - server_param.setString( param.key(), param.value().get< std::string >() ); - } - else - { - std::cout << "Unsupported value type. name=" << param.key() << ", value=" << param.value() << std::endl; - } - } - - return handler.handleServerParam( server_param ); -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::parsePlayerParam( const nlohmann::json & data, - Handler & handler ) -{ - PlayerParamT player_param; - for ( const auto & param : data.at( "params" ).items() ) - { - if ( param.value().is_number_integer() ) - { - player_param.setInt( param.key(), param.value().get< int >() ); - } - else if ( param.value().is_number() ) - { - player_param.setDouble( param.key(), param.value().get< double >() ); - } - else if ( param.value().is_boolean() ) - { - player_param.setBool( param.key(), param.value().get< bool >() ); - } - else - { - std::cout << "Unsupported value type. name=" << param.key() << ", value=" << param.value() << std::endl; - } - } - - return handler.handlePlayerParam( player_param ); -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::Impl::parsePlayerType( const nlohmann::json & data, - Handler & handler ) -{ - if ( ! data.contains( "id" ) ) - { - return false; - } - - PlayerTypeT ptype; - - try - { - ptype.id_ = data.at( "id" ); - } - catch ( std::exception & e ) - { - std::cout << "Could not read the player type id.\n" - << e.what() << std::endl; - return true; - } - - for ( const auto & param : data.at( "params" ).items() ) - { - if ( param.value().is_number() ) - { - ptype.setDouble( param.key(), param.value().get< double >() ); - } - else - { - std::cout << "Unsupported value type. name=" << param.key() << ", value=" << param.value() << std::endl; - } - } - - return handler.handlePlayerType( ptype ); -} - -/*-------------------------------------------------------------------*/ -/*-------------------------------------------------------------------*/ -/*-------------------------------------------------------------------*/ - -/*-------------------------------------------------------------------*/ -ParserJSON::ParserJSON() - : M_impl( new Impl() ) -{ - -} - -/*-------------------------------------------------------------------*/ -bool -ParserJSON::parse( std::istream & is, - Handler & handler ) -{ - // streampos must be the first point!!! - is.seekg( 0 ); - - if ( ! is.good() ) - { - return false; - } - - - std::string line; - std::getline( is, line ); // skip the first line, "ULG6" - - nlohmann::json rcg; - try - { - is >> rcg; - } - catch ( std::exception & e ) - { - std::cerr << "(rcss::rcg::ParserJSON::parse) Could not read the valid json.\n" - << e.what() << std::endl; - return false; - } - - if ( ! rcg.is_array() ) - { - std::cerr << "(rcss::rcg::ParserJSON::parse) Error. RCG is not an array" << std::endl; - return false; - } - - for ( const nlohmann::json & data : rcg ) - { - if ( ! M_impl->parseData( data, handler ) ) - { - return false; - } - } - - while ( std::getline( is, line ) ) - { - // skip all - } - - return handler.handleEOF(); -} - -/*-------------------------------------------------------------------*/ -/*! - - */ -bool -ParserJSON::parseData( const std::string & input, - Handler & handler ) -{ - nlohmann::json data; - try - { - data = nlohmann::json::parse( input ); - } - catch ( std::exception & e ) - { - std::cerr << "(rcss::rcg::ParserJSON::parseData) Could not read the valid json.\n" - << e.what() << std::endl; - return false; - } - - return M_impl->parseData( data, handler ); -} - -} // end of namespace -} // end of namespace diff --git a/rcss/rcg/parser_simdjson.cpp b/rcss/rcg/parser_simdjson.cpp new file mode 100644 index 0000000..51672d7 --- /dev/null +++ b/rcss/rcg/parser_simdjson.cpp @@ -0,0 +1,646 @@ +// -*-c++-*- + +/*! + \file parser_json.cpp + \brief rcg v6 (json) parser Source File. +*/ + +/* + *Copyright: + + Copyright (C) Hidehisa AKIYAMA + + This code is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + *EndCopyright: + */ + +///////////////////////////////////////////////////////////////////// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "parser_simdjson.h" + +#include "handler.h" +#include "types.h" +#include "util.h" + +#include "simdjson/simdjson.h" + +#include +#include + +namespace rcss { +namespace rcg { + + +struct ParserSimdJSON::Impl { + + using Func = std::function< bool( simdjson::ondemand::value & val, Handler & handler ) >; + std::unordered_map< std::string, Func > funcs_; + //std::unordered_map< simdjson::ondemand::raw_json_string, Func > funcs_; + + Impl(); + + bool parseData( simdjson::ondemand::field & field, + Handler & handler ); + + bool parseVersion( simdjson::ondemand::value & val, + Handler & handler ); + bool parseTimestamp( simdjson::ondemand::value & val, + Handler & handler ); + bool parseServerParam( simdjson::ondemand::value & val, + Handler & handler ); + bool parsePlayerParam( simdjson::ondemand::value & val, + Handler & handler ); + bool parsePlayerType( simdjson::ondemand::value & val, + Handler & handler ); + bool parseTeamGraphic( simdjson::ondemand::value & val, + Handler & handler ); + bool parsePlaymode( simdjson::ondemand::value & val, + Handler & handler ); + bool parseTeam( simdjson::ondemand::value & val, + Handler & handler ); + bool parseMsg( simdjson::ondemand::value & val, + Handler & handler ); + bool parseShow( simdjson::ondemand::value & val, + Handler & handler ); +}; + +/*-------------------------------------------------------------------*/ +ParserSimdJSON::Impl::Impl() +{ + funcs_["\"version\""] + = [this]( simdjson::ondemand::value & val, Handler & handler ) -> bool + { + return this->parseVersion( val, handler ); + }; + funcs_["\"timestamp\""] + = [this]( simdjson::ondemand::value & val, Handler & handler ) -> bool + { + return this->parseTimestamp( val, handler ); + }; + funcs_["\"server_param\""] + = [this]( simdjson::ondemand::value & val, Handler & handler ) -> bool + { + return this->parseServerParam( val, handler ); + }; + funcs_["\"player_param\""] + = [this]( simdjson::ondemand::value & val, Handler & handler ) -> bool + { + return this->parsePlayerParam( val, handler ); + }; + funcs_["\"player_type\""] + = [this]( simdjson::ondemand::value & val, Handler & handler ) -> bool + { + return this->parsePlayerType( val, handler ); + }; + funcs_["\"team_graphic\""] + = [this]( simdjson::ondemand::value & val, Handler & handler ) -> bool + { + return this->parseTeamGraphic( val, handler ); + }; + funcs_["\"playmode\""] + = [this]( simdjson::ondemand::value & val, Handler & handler ) -> bool + { + return this->parsePlaymode( val, handler ); + }; + funcs_["\"team\""] + = [this]( simdjson::ondemand::value & val, Handler & handler ) -> bool + { + return this->parseTeam( val, handler ); + }; + funcs_["\"msg\""] + = [this]( simdjson::ondemand::value & val, Handler & handler ) -> bool + { + return this->parseMsg( val, handler ); + }; + funcs_["\"show\""] + = [this]( simdjson::ondemand::value & val, Handler & handler ) -> bool + { + return this->parseShow( val, handler ); + }; +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::Impl::parseData( simdjson::ondemand::field & field, + Handler & handler ) +{ + //std::string_view key = field.key_raw_json_token(); + //std::string str_key( key.substr( 1, key.length() - 2 ) ); + //std::string str_key( key ); + //std::cerr << "(ParserSimdJSON::Impl::parseData) key=" << field.key() << " str=" << str_key << std::endl; + //std::unordered_map< std::string, Func >::iterator it = funcs_.find( str_key ); + std::string key( field.key_raw_json_token() ); + std::unordered_map< std::string, Func >::iterator it = funcs_.find( key ); + if ( it == funcs_.end() ) + { + std::cerr << "(ParserSimdJSON::Impl::parseData) func not found. key=" << key + << std::endl; + return false; + } + + if ( ! it->second( field.value(), handler ) ) + { + return false; + } + + return true; +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::Impl::parseVersion( simdjson::ondemand::value & /*val*/, + Handler & /*handler*/ ) +{ + //std::cerr << "version " << val << std::endl; + return true; +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::Impl::parseTimestamp( simdjson::ondemand::value & /*val*/, + Handler & /*handler*/ ) +{ + //std::cerr << "timestamp " << val << std::endl; + return true; +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::Impl::parseServerParam( simdjson::ondemand::value & val, + Handler & handler ) +{ + ServerParamT server_param; + + for ( simdjson::ondemand::field param : val.get_object() ) + { + std::string_view key = param.key_raw_json_token(); + if ( key.length() < 3 + || *key.begin() != '\"' + || *key.rbegin() != '\"' ) + { + std::cerr << "(ParserSimdJSON::parseServerParam) Error: unexpected key [" << key << "]" << std::endl; + return false; + } + + const std::string name( key.substr( 1, key.length() - 2 ) ); + const std::string value( param.value().raw_json_token() ); + + server_param.setValue( name, value ); + } + + return handler.handleServerParam( server_param ); +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::Impl::parsePlayerParam( simdjson::ondemand::value & val, + Handler & handler ) +{ + PlayerParamT player_param; + + for ( simdjson::ondemand::field param : val.get_object() ) + { + std::string_view key = param.key_raw_json_token(); + if ( key.length() < 3 + || *key.begin() != '\"' + || *key.rbegin() != '\"' ) + { + std::cerr << "(ParserSimdJSON::parsePlayerParam) Error: unexpected key [" << key << "]" << std::endl; + return false; + } + + const std::string name( key.substr( 1, key.length() - 2 ) ); + const std::string value( param.value().raw_json_token() ); + + player_param.setValue( name, value ); + } + + return handler.handlePlayerParam( player_param ); +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::Impl::parsePlayerType( simdjson::ondemand::value & val, + Handler & handler ) +{ + PlayerTypeT player_type; + + for ( simdjson::ondemand::field param : val.get_object() ) + { + std::string_view key = param.key_raw_json_token(); + if ( key.length() < 3 + || *key.begin() != '\"' + || *key.rbegin() != '\"' ) + { + std::cerr << "(ParserSimdJSON::parsePlayerType) Error: unexpected key [" << key << "]" << std::endl; + return false; + } + + const std::string name( key.substr( 1, key.length() - 2 ) ); + const std::string value( param.value().raw_json_token() ); + + player_type.setValue( name, value ); + } + + return handler.handlePlayerType( player_type ); +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::Impl::parseTeamGraphic( simdjson::ondemand::value & val, + Handler & handler ) +{ + bool result = false; + try + { + std::string_view side = val["side"].get_string(); + int64_t x = val["x"].get_int64(); + int64_t y = val["y"].get_int64(); + + std::vector< std::string > xpm_data; + for ( simdjson::ondemand::value s : val["xpm"].get_array() ) + { + std::string str; + s.get_string( str ); + xpm_data.push_back( str ); + } + + result = handler.handleTeamGraphic( side[0], x, y, xpm_data ); + } + catch ( std::exception & e ) + { + std::cerr << "(ParserSimdJSON::TeamGraphic) " << e.what() << std::endl; + } + + return result; +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::Impl::parsePlaymode( simdjson::ondemand::value & val, + Handler & handler ) +{ + bool result = false; + try + { + int64_t time = -1; + simdjson::error_code err = val["time"].get_int64().get( time ); + if ( err != simdjson::SUCCESS ) time = -1; + + std::string_view playmode = val["mode"].get_string(); + + result = handler.handlePlayMode( time, std::string( playmode ) ); + } + catch ( std::exception & e ) + { + std::cerr << "(ParserSimdJSON::parsePlaymode) " << e.what() << std::endl; + } + + return result; +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::Impl::parseTeam( simdjson::ondemand::value & val, + Handler & handler ) +{ + bool result = false; + try + { + simdjson::error_code err = simdjson::SUCCESS; + + TeamT team_l; + TeamT team_r; + + int64_t time = -1; + err = val["time"].get_int64().get( time ); + if ( err != simdjson::SUCCESS ) time = -1; + + uint64_t i = 0; + + if ( val["l"]["name"].is_string() ) team_l.name_ = val["l"]["name"].get_string().value(); + team_l.score_ = val["l"]["score"].get_uint64(); + + err = val["l"]["pen_score"].get_uint64().get( i ); + if ( err == simdjson::SUCCESS ) team_l.pen_score_ = i; + + err = val["l"]["pen_miss"].get_uint64().get( i ); + if ( err == simdjson::SUCCESS ) team_l.pen_miss_ = i; + + if ( val["r"]["name"].is_string() ) team_r.name_ = val["r"]["name"].get_string().value(); + team_r.score_ = val["r"]["score"].get_uint64(); + + err = val["r"]["pen_score"].get_uint64().get( i ); + if ( err == simdjson::SUCCESS ) team_r.pen_score_ = i; + + err = val["r"]["pen_miss"].get_uint64().get( i ); + if ( err == simdjson::SUCCESS ) team_r.pen_miss_ = i; + + result = handler.handleTeam( time, team_l, team_r ); + } + catch ( std::exception & e ) + { + std::cerr << "(ParserSimdJSON::parseTeam) " << e.what() << std::endl; + } + + return result; +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::Impl::parseMsg( simdjson::ondemand::value & val, + Handler & handler ) +{ + bool result = false; + try + { + result = handler.handleMsg( val["time"].get_int64(), + val["board"].get_int64(), + std::string( val["message"].get_string().value() ) ); + } + catch ( std::exception & e ) + { + std::cerr << "(ParserSimdJSON::parseMsg) " << e.what() << std::endl; + } + + return result; +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::Impl::parseShow( simdjson::ondemand::value & val, + Handler & handler ) +{ + ShowInfoT show; + + simdjson::error_code err = simdjson::SUCCESS; + int64_t itmp; + double dtmp; + std::string_view stmp; + + try + { + show.time_ = val["time"].get_int64(); + err = val["stime"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.stime_ = itmp; + } + catch ( std::exception & e ) + { + std::cerr << "(ParserSimdJSON::parseShow) time part: " << e.what() << std::endl; + return false; + } + + { + err = val["mode"].get_string().get( stmp ); + if ( err == simdjson::SUCCESS ) + { + if ( ! handler.handlePlayMode( show.time_, to_playmode_enum( std::string( stmp ) ) ) ) + { + return false; + } + } + } + { + simdjson::simdjson_result< simdjson::ondemand::value > teams = val["team"]; + if ( teams.error() == simdjson::SUCCESS ) + { + if ( ! parseTeam( teams.value(), handler ) ) + { + return false; + } + } + } + + try + { + show.ball_.x_ = val["ball"]["x"].get_double(); + show.ball_.y_ = val["ball"]["y"].get_double(); + show.ball_.vx_ = val["ball"]["vx"].get_double(); + show.ball_.vy_ = val["ball"]["vy"].get_double(); + } + catch ( std::exception & e ) + { + std::cerr << "(ParserSimdJSON::parseShow) ball part: " << e.what() << std::endl; + return false; + } + + size_t i = 0; + try + { + for ( simdjson::ondemand::value p : val["players"].get_array() ) + { + if ( i >= 22 ) + { + std::cerr << "(ParserSimdJSON::parseShow) player index overflow " << i << std::endl; + return false; + } + + // begin + stmp = p["side"].get_string(); + show.player_[i].side_ = stmp[0]; + show.player_[i].unum_ = p["unum"].get_int64(); + show.player_[i].type_ = p["type"].get_int64(); + show.player_[i].state_ = p["state"].get_int64(); + + // pos + show.player_[i].x_ = p["x"].get_double(); + show.player_[i].y_ = p["y"].get_double(); + show.player_[i].vx_ = p["vx"].get_double(); + show.player_[i].vy_ = p["vy"].get_double(); + show.player_[i].body_ = p["body"].get_double(); + show.player_[i].neck_ = p["neck"].get_double(); + + // arm + err = p["px"].get_double().get( dtmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].point_x_ = dtmp; + err = p["py"].get_double().get( dtmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].point_y_ = dtmp; + + // view mode + stmp = p["vq"].get_string(); + show.player_[i].view_quality_ = ( stmp == "h" ? true : false ); + show.player_[i].view_width_ = p["vw"].get_double(); + + // focus point + err = p["fdist"].get_double().get( dtmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].focus_dist_ = dtmp; + err = p["fdir"].get_double().get( dtmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].focus_dir_ = dtmp; + + // stamina + show.player_[i].stamina_ = p["stamina"].get_double(); + show.player_[i].effort_ = p["effort"].get_double(); + show.player_[i].recovery_ = p["recovery"].get_double(); + show.player_[i].stamina_capacity_ = p["capacity"].get_double(); + + // focus + err = p["fside"].get_string().get( stmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].focus_side_ = stmp[0]; + err = p["fnum"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].focus_unum_ = itmp; + + // count + err = p["kick"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].kick_count_ = itmp; + err = p["dash"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].dash_count_ = itmp; + err = p["turn"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].turn_count_ = itmp; + err = p["catch"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].catch_count_ = itmp; + err = p["move"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].move_count_ = itmp; + err = p["turn_neck"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].turn_neck_count_ = itmp; + err = p["change_view"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].change_view_count_ = itmp; + err = p["say"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].say_count_ = itmp; + err = p["tackle"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].tackle_count_ = itmp; + err = p["pointto"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].pointto_count_ = itmp; + err = p["attentionto"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].attentionto_count_ = itmp; + err = p["change_focus"].get_int64().get( itmp ); + if ( err == simdjson::SUCCESS ) show.player_[i].change_focus_count_ = itmp; + + ++i; + } + } + catch ( std::exception & e ) + { + std::cerr << "(ParserSimdJSON::parseShow) player part " << i << ": " << e.what() << std::endl; + } + + return handler.handleShow( show ); +} + +/*-------------------------------------------------------------------*/ +/*-------------------------------------------------------------------*/ +/*-------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------*/ +ParserSimdJSON::ParserSimdJSON() + : M_impl( new Impl() ) +{ + // std::cerr << "(ParserSimdJSON) create" << std::endl; +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::parse( std::istream & is, + Handler & handler ) const +{ + // streampos must be the first point!!! + is.seekg( 0 ); + + if ( ! is.good() ) + { + return false; + } + + handler.handleLogVersion( REC_VERSION_JSON ); + + try + { + simdjson::ondemand::parser parser; + simdjson::padded_string json( std::string( std::istreambuf_iterator< char >( is ), {} ) ); + simdjson::ondemand::document rcg = parser.iterate( json ); + simdjson::ondemand::array root_array = rcg.get_array(); + + for ( simdjson::ondemand::object data : root_array ) + { + for ( simdjson::ondemand::field field : data ) + { + if ( ! M_impl->parseData( field, handler ) ) + { + return false; + } + } + } + } + catch ( std::exception & e ) + { + std::cerr << "(ParserSimdJSON::parse) ERROR\n\t" << e.what() << std::endl; + return false; + } + + handler.handleEOF(); + return true; +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::parse( const std::string & filepath, + Handler & handler ) const +{ + handler.handleLogVersion( REC_VERSION_JSON ); + + try + { + simdjson::ondemand::parser parser; + simdjson::padded_string json = simdjson::padded_string::load( filepath ); + simdjson::ondemand::document rcg = parser.iterate( json ); + simdjson::ondemand::array root_array = rcg.get_array(); + + for ( simdjson::ondemand::object data : root_array ) + { + for ( simdjson::ondemand::field field : data ) + { + if ( ! M_impl->parseData( field, handler ) ) + { + return false; + } + } + } + } + catch ( std::exception & e ) + { + std::cerr << "(ParserSimdJSON::parse) ERROR\n\t" << e.what() << std::endl; + return false; + } + + handler.handleEOF(); + return true; +} + +/*-------------------------------------------------------------------*/ +bool +ParserSimdJSON::parseData( const std::string & input, + Handler & handler ) const +{ + simdjson::ondemand::parser parser; + simdjson::padded_string json( input ); + simdjson::ondemand::document data = parser.iterate( json ); + + for ( simdjson::ondemand::field field : data.get_object() ) + { + if ( ! M_impl->parseData( field, handler ) ) + { + return false; + } + } + + return true; +} + +} +} diff --git a/rcss/rcg/parser_json.h b/rcss/rcg/parser_simdjson.h similarity index 78% rename from rcss/rcg/parser_json.h rename to rcss/rcg/parser_simdjson.h index c2a46e7..0ca9a4b 100644 --- a/rcss/rcg/parser_json.h +++ b/rcss/rcg/parser_simdjson.h @@ -1,8 +1,8 @@ // -*-c++-*- /*! - \file parser_json.h - \brief rcg v6 (JSON format) parser Header File. + \file parser_simdjson.h + \brief rcg v6 (json) parser Header File. */ /* @@ -29,8 +29,8 @@ ///////////////////////////////////////////////////////////////////// -#ifndef RCSS_RCG_PARSER_JSON_H -#define RCSS_RCG_PARSER_JSON_H +#ifndef RCSS_RCG_PARSER_SIMDJSON_H +#define RCSS_RCG_PARSER_SIMDJSON_H #include #include @@ -41,11 +41,12 @@ namespace rcss { namespace rcg { + /*! - \class ParserJSON - \brief rcg v6 parser class + \class ParserSimdJSON + \brief JSON rcg parser class */ -class ParserJSON +class ParserSimdJSON : public Parser { private: struct Impl; @@ -54,9 +55,9 @@ class ParserJSON public: /*! - \brief create a Impl instance - */ - ParserJSON(); + \brief create the Impl instance + */ + ParserSimdJSON(); /*! \brief get supported rcg version @@ -64,9 +65,9 @@ class ParserJSON */ virtual int version() const override - { - return REC_VERSION_JSON; - } + { + return REC_VERSION_JSON; + } /*! \brief parse input stream @@ -75,9 +76,12 @@ class ParserJSON \retval true, if successfuly parsed. \retval false, if incorrect format is detected. */ - virtual bool parse( std::istream & is, - Handler & handler ) override; + Handler & handler ) const override; + + bool parse( const std::string & filepath, + Handler & handler ) const override; + /*! \brief assume to parse one monitor packet. @@ -90,11 +94,12 @@ class ParserJSON Second, call each data item parsing method. */ bool parseData( const std::string & input, - Handler & handler ); + Handler & handler ) const; + }; -} // end of namespace -} // end of namespace +} +} #endif diff --git a/rcss/rcg/parser_v1.cpp b/rcss/rcg/parser_v1.cpp index 949d4cf..39d59f3 100644 --- a/rcss/rcg/parser_v1.cpp +++ b/rcss/rcg/parser_v1.cpp @@ -37,31 +37,18 @@ #include "handler.h" #include "types.h" -#include "util.h" - #include -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_WINDOWS_H -#include -#endif - namespace rcss { namespace rcg { /*-------------------------------------------------------------------*/ -ParserV1::ParserV1() - : M_time( -1 ) -{ - -} +/*! -/*-------------------------------------------------------------------*/ +*/ bool ParserV1::parse( std::istream & is, - Handler & handler ) + Handler & handler ) const { // streampos must be the first point!!! is.seekg( 0 ); @@ -72,144 +59,41 @@ ParserV1::parse( std::istream & is, } // register log version - // Because rcg v1 does not contain a version information, - // REC_OLD_VERSION is always set. + // Because rcg v1 does not contain version information, + // REC_OLD_VERSION is set without reading. if ( ! handler.handleLogVersion( REC_OLD_VERSION ) ) { return false; } + dispinfo_t info; while ( is.good() ) { - dispinfo_t disp; - is.read( reinterpret_cast< char * >( &disp ), sizeof( dispinfo_t ) ); + is.read( reinterpret_cast< char* >( &info ), sizeof( dispinfo_t ) ); if ( is.gcount() != sizeof( dispinfo_t ) ) { if ( is.eof() ) { break; } - + //std::cerr << "failed to read dispinfo " << std::endl; return false; } - if ( ! handleDisp( disp, handler ) ) + // check cycle order and so on. + if ( ! handler.handleDispInfo( info ) ) { return false; } } - if ( ! is.eof() ) + if ( is.eof() ) { - return false; - } - - return handler.handleEOF(); -} - -/*-------------------------------------------------------------------*/ -bool -ParserV1::handleDisp( const dispinfo_t & disp, - Handler & handler ) - -{ - const Int16 mode = ntohs( disp.mode ); - switch ( mode ) { - case NO_INFO: - return true; - - case SHOW_MODE: - return handleShow( disp.body.show, handler ); - - case MSG_MODE: - return handleMsg( disp.body.msg, handler ); - - case DRAW_MODE: - return handleDraw( disp.body.draw, handler ); - - case BLANK_MODE: - return true; - - default: - std::cerr << "(rcss::rcg::ParserV1::parseDisp) Unknown mode [" << mode << "]" << std::endl; - break; + return handler.handleEOF(); } return false; } -/*-------------------------------------------------------------------*/ -bool -ParserV1::handleShow( const showinfo_t & show, - Handler & handler ) - -{ - ShowInfoT new_show; - TeamT team_l, team_r; - - const PlayMode pmode = static_cast< PlayMode >( show.pmode ); - convert( show, new_show ); - convert( show.team[0], team_l ); - convert( show.team[1], team_r ); - - M_time = new_show.time_; - - return ( handler.handlePlayMode( new_show.time_, pmode ) - && handler.handleTeam( new_show.time_, team_l, team_r ) - && handler.handleShow( new_show ) ); -} - -/*-------------------------------------------------------------------*/ -bool -ParserV1::handleMsg( const msginfo_t & msg, - Handler & handler ) -{ - handler.handleMsg( M_time, - ntohs( msg.board ), - msg.message ); - return true; -} - -/*-------------------------------------------------------------------*/ -bool -ParserV1::handleDraw( const drawinfo_t & draw, - Handler & handler ) - -{ - switch ( ntohs( draw.mode ) ) { - case DrawClear: - handler.handleDrawClear( M_time ); - return true; - - case DrawPoint: - handler.handleDrawPoint( M_time, - PointT( nstohf( draw.object.pinfo.x ), - nstohf( draw.object.pinfo.y ), - draw.object.pinfo.color ) ); - return true; - case DrawCircle: - handler.handleDrawCircle( M_time, - CircleT( nstohf( draw.object.cinfo.x ), - nstohf( draw.object.cinfo.y ), - nstohf( draw.object.cinfo.r ), - draw.object.cinfo.color ) ); - return true; - case DrawLine: - handler.handleDrawLine( M_time, - LineT( nstohf( draw.object.linfo.x1 ), - nstohf( draw.object.linfo.y1 ), - nstohf( draw.object.linfo.x2 ), - nstohf( draw.object.linfo.y2 ), - draw.object.linfo.color ) ); - return true; - default: - std::cerr << "(rcss::rcg::ParserV1::parseDraw) Unknown draw mode " << ntohs( draw.mode ) - << std::endl; - return false; - } - - return true; -} - } // end of namespace } // end of namespace diff --git a/rcss/rcg/parser_v1.h b/rcss/rcg/parser_v1.h index fc80aee..43d3814 100644 --- a/rcss/rcg/parser_v1.h +++ b/rcss/rcg/parser_v1.h @@ -44,55 +44,26 @@ namespace rcg { */ class ParserV1 : public Parser { -protected: - - //! The last parsed game time - int M_time; - public: - /*! - \brief default constructor - */ - ParserV1(); /*! \brief get supported rcg version \return version number */ - virtual int version() const override - { - return REC_OLD_VERSION; - } + { + return REC_OLD_VERSION; + } /*! \brief parse input stream - \param is input stream + \param is reference to the imput stream (usually ifstream/gzifstream). \param handler reference to the rcg data handler. \retval true, if successfuly parsed. \retval false, if incorrect format is detected. */ - virtual bool parse( std::istream & is, - Handler & handler ) override; - - /*! - \brief handle dispinfo_t. This method can be used to parse the monitor packet. - \param disp the read/received data - \param handler reference to the data handler - */ - bool handleDisp( const dispinfo_t & disp, - Handler & handler ); - -protected: - - bool handleShow( const showinfo_t & show, - Handler & handler ); - bool handleMsg( const msginfo_t & msg, - Handler & handler ); - bool handleDraw( const drawinfo_t & draw, - Handler & handler ); - + Handler & handler ) const override; }; } // end of namespace diff --git a/rcss/rcg/parser_v2.cpp b/rcss/rcg/parser_v2.cpp index d52c905..2ef5909 100644 --- a/rcss/rcg/parser_v2.cpp +++ b/rcss/rcg/parser_v2.cpp @@ -33,13 +33,6 @@ #include #endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_WINDOWS_H -#include -#endif - #include "parser_v2.h" #include "handler.h" @@ -48,6 +41,13 @@ #include #include +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_WINDOWS_H +#include +#endif + namespace rcss { namespace rcg { @@ -57,7 +57,7 @@ namespace rcg { */ bool ParserV2::parse( std::istream & is, - Handler & handler ) + Handler & handler ) const { // streampos must be the first point!!! is.seekg( 0 ); @@ -87,12 +87,12 @@ ParserV2::parse( std::istream & is, } } - if ( ! is.eof() ) + if ( is.eof() ) { - return false; + return handler.handleEOF(); } - return handler.handleEOF(); + return false; } /*-------------------------------------------------------------------*/ @@ -101,10 +101,13 @@ ParserV2::parse( std::istream & is, */ bool ParserV2::parseData( std::istream & is, - Handler & handler ) + Handler & handler ) const { - Int16 mode; - if ( ! is.read( reinterpret_cast< char * >( &mode ), sizeof( Int16 ) ) ) + // chedk data mode. + dispinfo_t info; + is.read( reinterpret_cast< char * >( &info.mode ), sizeof( Int16 ) ); + + if ( ! is.good() ) { if ( is.eof() ) { @@ -113,22 +116,33 @@ ParserV2::parseData( std::istream & is, return false; } - switch ( ntohs( mode ) ) { + // read each data block + switch ( ntohs( info.mode ) ) { case NO_INFO: return true; - case SHOW_MODE: - return parseShow( is, handler ); + is.read( reinterpret_cast< char* >( &info.body.show ), + sizeof( showinfo_t ) ); + if ( is.gcount() == sizeof( showinfo_t ) ) + { + return handler.handleShowInfo( info.body.show ); + } break; - case MSG_MODE: - return parseMsg( is, handler ); - + return parseMsgInfo( is, handler ); + break; case DRAW_MODE: - return parseDraw( is, handler ); - + is.read( reinterpret_cast< char* >( &info.body.draw ), + sizeof( drawinfo_t ) ); + if ( is.gcount() == sizeof( drawinfo_t ) ) + { + return true; + } + break; default: - std::cerr << "(rcss::rcg::ParserV2::parseData) Unknown mode" << ntohs( mode ) << std::endl;; + std::cerr << __FILE__ << ':' << __LINE__ + << " Unknown mode" << htons( info.mode ) + << std::endl;; break; } @@ -136,30 +150,17 @@ ParserV2::parseData( std::istream & is, } /*-------------------------------------------------------------------*/ -bool -ParserV2::parseShow( std::istream & is, - Handler & handler ) -{ - showinfo_t show; - is.read( reinterpret_cast< char * >( &show ), sizeof( showinfo_t ) ); - - if ( is.gcount() != sizeof( showinfo_t ) ) - { - return false; - } - - return handleShow( show, handler ); -} +/*! -/*-------------------------------------------------------------------*/ +*/ bool -ParserV2::parseMsg( std::istream & is, - Handler & handler ) +ParserV2::parseMsgInfo( std::istream & is, + Handler & handler ) const { bool result = false; Int16 board; - is.read( reinterpret_cast< char * >( &board ), sizeof( Int16 ) ); + is.read( reinterpret_cast< char* >( &board ), sizeof( Int16 ) ); if ( is.gcount() != sizeof( Int16 ) ) { return false; @@ -167,7 +168,7 @@ ParserV2::parseMsg( std::istream & is, board = ntohs( board ); Int16 len; - is.read( reinterpret_cast< char * >( &len ), sizeof( Int16 ) ); + is.read( reinterpret_cast< char* >( &len ), sizeof( Int16 ) ); if ( is.gcount() != sizeof( Int16 ) ) { return false; @@ -183,29 +184,12 @@ ParserV2::parseMsg( std::istream & is, len = std::strlen( msg ); } - result = handler.handleMsg( M_time, board, std::string( msg, len ) ); + result = handler.handleMsgInfo( board, std::string( msg, len ) ); } delete [] msg; return result; } - -/*-------------------------------------------------------------------*/ -bool -ParserV2::parseDraw( std::istream & is, - Handler & handler ) -{ - drawinfo_t draw; - is.read( reinterpret_cast< char * >( &draw ), sizeof( drawinfo_t ) ); - - if ( is.gcount() != sizeof( drawinfo_t ) ) - { - return false; - } - - return handleDraw( draw, handler ); -} - } // end of namespace } // end of namespace diff --git a/rcss/rcg/parser_v2.h b/rcss/rcg/parser_v2.h index 98432d1..b990f67 100644 --- a/rcss/rcg/parser_v2.h +++ b/rcss/rcg/parser_v2.h @@ -32,7 +32,8 @@ #ifndef RCSS_RCG_PARSER_V2_H #define RCSS_RCG_PARSER_V2_H -#include +#include +#include namespace rcss { namespace rcg { @@ -42,29 +43,27 @@ namespace rcg { \brief rcg v2 parser */ class ParserV2 - : public ParserV1 { + : public Parser { public: /*! \brief get supported rcg version \return version number */ - virtual int version() const override - { - return REC_VERSION_2; - } + { + return REC_VERSION_2; + } /*! \brief parse input stream. hander will handle each data block. - \param is input stream. + \param is reference to the imput stream (usually ifstream). \param handler reference to the rcg data handler. \retval true if successfuly parsed. \retval false if incorrect format is detected. */ - virtual bool parse( std::istream & is, - Handler & handler ) override; + Handler & handler ) const override; private: /*! @@ -79,37 +78,17 @@ class ParserV2 Second, call matched handler method. */ bool parseData( std::istream & is, - Handler & handler ); - - /*! - \brief parse SHOW_MODE info(showinfo_t) - \param is reference to the input stream - \param handler reference to the data handler object - \retval true if successfully parsed. - \retval false if failed to parse. - */ - bool parseShow( std::istream & is, - Handler & handler ); - - /*! - \brief parse MSG_MODE info(msginfo_t) - \param is reference to the input stream - \param handler reference to the data handler object - \retval true if successfully parsed. - \retval false if failed to parse. - */ - bool parseMsg( std::istream & is, - Handler & handler ); + Handler & handler ) const; /*! - \brief parse DRAW_MODE info(drawinfo_t) + \brief parse MSG_MODE info(msg_info_t) \param is reference to the input stream \param handler reference to the data handler object \retval true if successfully parsed. \retval false if failed to parse. */ - bool parseDraw( std::istream & is, - Handler & handler ); + bool parseMsgInfo( std::istream & is, + Handler & handler ) const; }; } // end of namespace diff --git a/rcss/rcg/parser_v3.cpp b/rcss/rcg/parser_v3.cpp index e9159e4..88a97d5 100644 --- a/rcss/rcg/parser_v3.cpp +++ b/rcss/rcg/parser_v3.cpp @@ -33,36 +33,31 @@ #include #endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_WINDOWS_H -#include -#endif - #include "parser_v3.h" #include "handler.h" #include "types.h" -#include "util.h" #include #include +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_WINDOWS_H +#include +#endif + namespace rcss { namespace rcg { /*-------------------------------------------------------------------*/ -ParserV3::ParserV3() - : M_time( -1 ) -{ - -} +/*! -/*-------------------------------------------------------------------*/ +*/ bool ParserV3::parse( std::istream & is, - Handler & handler ) + Handler & handler ) const { // streampos must be the first point!!! is.seekg( 0 ); @@ -92,22 +87,25 @@ ParserV3::parse( std::istream & is, } } - if ( ! is.eof() ) + if ( is.eof() ) { - return false; + return handler.handleEOF(); } - return handler.handleEOF(); + return false; } /*-------------------------------------------------------------------*/ +/*! + +*/ bool ParserV3::parseData( std::istream & is, - Handler & handler ) + Handler & handler ) const { // chedk data mode. Int16 mode; - is.read( reinterpret_cast< char * >( &mode ), sizeof( Int16 ) ); + is.read( reinterpret_cast< char* >( &mode ), sizeof( Int16 ) ); if ( ! is.good() ) { @@ -119,78 +117,68 @@ ParserV3::parseData( std::istream & is, return false; } + //std::cerr << "read mode = " << (int)ntohs( mode ) << std::endl; + // read each data block switch ( ntohs( mode ) ) { case NO_INFO: return true; - case SHOW_MODE: - return parseShortShow( is, handler ); - + return parseShowInfo( is, handler ); case MSG_MODE: - return parseMsg( is, handler ); - + return parseMsgInfo( is, handler ); case PM_MODE: return parsePlayMode( is, handler ); - case TEAM_MODE: - return parseTeam( is, handler ); - + return parseTeamInfo( is, handler ); case PT_MODE: return parsePlayerType( is, handler ); - case PARAM_MODE: return parseServerParam( is, handler ); - case PPARAM_MODE: return parsePlayerParam( is, handler ); - case BLANK_MODE: - std::cerr << "(rcss::rcg::ParserV3) BLANK mode is not supported." << std::endl;; - break; - case DRAW_MODE: - std::cerr << "(rcss::rcg::ParserV3) DRAW mode is not supported." << std::endl;; - break; - default: - std::cerr << "(rcss::rcg::ParserV3) Unknown mode" << ntohs( mode ) << std::endl;; + std::cerr << __FILE__ << ':' << __LINE__ + << " Unknown mode" << htons( mode ) + << std::endl;; break; - } return false; } /*-------------------------------------------------------------------*/ +/*! + +*/ bool -ParserV3::parseShortShow( std::istream & is, - Handler & handler ) +ParserV3::parseShowInfo( std::istream & is, + Handler & handler ) const { short_showinfo_t2 short_show; - is.read( reinterpret_cast< char * >( &short_show ), sizeof( short_showinfo_t2 ) ); - - if ( is.gcount() != sizeof( short_showinfo_t2 ) ) + is.read( reinterpret_cast< char* >( &short_show ), + sizeof( short_showinfo_t2 ) ); + if ( is.gcount() == sizeof( short_showinfo_t2 ) ) { - return false; + return handler.handleShortShowInfo2( short_show ); } - ShowInfoT new_show; - convert( short_show, new_show ); - - M_time = static_cast< int >( new_show.time_ ); - - return handler.handleShow( new_show ); + return false; } /*-------------------------------------------------------------------*/ +/*! + +*/ bool -ParserV3::parseMsg( std::istream & is, - Handler & handler ) +ParserV3::parseMsgInfo( std::istream & is, + Handler & handler ) const { bool result = false; Int16 board; - is.read( reinterpret_cast< char * >( &board ), sizeof( Int16 ) ); + is.read( reinterpret_cast< char* >( &board ), sizeof( Int16 ) ); if ( is.gcount() != sizeof( Int16 ) ) { return false; @@ -198,7 +186,7 @@ ParserV3::parseMsg( std::istream & is, board = ntohs( board ); Int16 len; - is.read( reinterpret_cast< char * >( &len ), sizeof( Int16 ) ); + is.read( reinterpret_cast< char* >( &len ), sizeof( Int16 ) ); if ( is.gcount() != sizeof( Int16 ) ) { return false; @@ -214,7 +202,7 @@ ParserV3::parseMsg( std::istream & is, len = std::strlen( msg ); } - result = handler.handleMsg( M_time, board, std::string( msg, len ) ); + result = handler.handleMsgInfo( board, std::string( msg, len ) ); } delete [] msg; @@ -222,19 +210,22 @@ ParserV3::parseMsg( std::istream & is, } /*-------------------------------------------------------------------*/ +/*! + +*/ bool ParserV3::parsePlayMode( std::istream & is, - Handler & handler ) + Handler & handler ) const { char pmode; - is.read( reinterpret_cast< char * >( &pmode ), sizeof( char ) ); - - if ( is.gcount() != sizeof( char ) ) + is.read( reinterpret_cast< char* >( &pmode ), + sizeof( char ) ); + if ( is.gcount() == sizeof( char ) ) { - return false; + return handler.handlePlayMode( pmode ); } - return handler.handlePlayMode( M_time, static_cast< PlayMode >( pmode ) ); + return false; } /*-------------------------------------------------------------------*/ @@ -242,42 +233,39 @@ ParserV3::parsePlayMode( std::istream & is, */ bool -ParserV3::parseTeam( std::istream & is, - Handler & handler ) +ParserV3::parseTeamInfo( std::istream & is, + Handler & handler ) const { team_t team[2]; - is.read( reinterpret_cast< char * >( team ), sizeof( team_t ) * 2 ); - - if ( is.gcount() != sizeof( team_t ) * 2 ) + is.read( reinterpret_cast< char* >( team ), + sizeof( team_t ) * 2 ); + if ( is.gcount() == sizeof( team_t ) * 2 ) { - return false; + return handler.handleTeamInfo( team[0], team[1] ); } - TeamT team_l, team_r; - convert( team[0], team_l ); - convert( team[1], team_r ); - - return handler.handleTeam( M_time, team_l, team_r ); + return false; } /*-------------------------------------------------------------------*/ +/*! + +*/ bool ParserV3::parsePlayerType( std::istream & is, - Handler & handler ) + Handler & handler ) const { - player_type_t ptype; - std::memset( &ptype, 0, sizeof( player_type_t ) ); - is.read( reinterpret_cast< char * >( &ptype ), sizeof( player_type_t ) ); + player_type_t ptinfo; + std::memset( &ptinfo, 0, sizeof( player_type_t ) ); - if ( is.gcount() != sizeof( player_type_t ) ) + is.read( reinterpret_cast< char* >( &ptinfo ), + sizeof( player_type_t ) ); + if ( is.gcount() == sizeof( player_type_t ) ) { - return false; + return handler.handlePlayerType( ptinfo ); } - PlayerTypeT new_type; - convert( ptype, new_type ); - - return handler.handlePlayerType( new_type ); + return false; } /*-------------------------------------------------------------------*/ @@ -286,21 +274,19 @@ ParserV3::parsePlayerType( std::istream & is, */ bool ParserV3::parseServerParam( std::istream & is, - Handler & handler ) + Handler & handler ) const { server_params_t sparams; std::memset( &sparams, 0, sizeof( server_params_t ) ); - is.read( reinterpret_cast< char * >( &sparams ), sizeof( server_params_t ) ); - if ( is.gcount() != sizeof( server_params_t ) ) + is.read( reinterpret_cast< char* >( &sparams ), + sizeof( server_params_t ) ); + if ( is.gcount() == sizeof( server_params_t ) ) { - return false; + return handler.handleServerParam( sparams ); } - ServerParamT new_params; - convert( sparams, new_params ); - - return handler.handleServerParam( new_params ); + return false; } /*-------------------------------------------------------------------*/ @@ -309,21 +295,19 @@ ParserV3::parseServerParam( std::istream & is, */ bool ParserV3::parsePlayerParam( std::istream & is, - Handler & handler ) + Handler & handler ) const { player_params_t pparams; std::memset( &pparams, 0, sizeof( player_params_t ) ); - is.read( reinterpret_cast< char * >( &pparams ), sizeof( pparams ) ); - if ( is.gcount() != sizeof( player_params_t ) ) + is.read( reinterpret_cast< char* >( &pparams ), + sizeof( pparams ) ); + if ( is.gcount() == sizeof( player_params_t ) ) { - return false; + return handler.handlePlayerParam( pparams ); } - PlayerParamT new_params; - convert( pparams, new_params ); - - return handler.handlePlayerParam( new_params ); + return false; } } // end of namespace diff --git a/rcss/rcg/parser_v3.h b/rcss/rcg/parser_v3.h index a3edf16..454c45e 100644 --- a/rcss/rcg/parser_v3.h +++ b/rcss/rcg/parser_v3.h @@ -41,28 +41,19 @@ namespace rcg { /*! \class ParserV3 \brief rcg v3 parser class -*/ + */ class ParserV3 : public Parser { -private: - - int M_time; //!< The last parsed game time - public: - /*! - \brief default constructor - */ - ParserV3(); - /*! \brief get supported rcg version \return version number - */ + */ int version() const override - { - return REC_VERSION_3; - } + { + return REC_VERSION_3; + } /*! \brief parse input stream @@ -72,7 +63,7 @@ class ParserV3 \retval false, if incorrect format is detected. */ bool parse( std::istream & is, - Handler & handler ) override; + Handler & handler ) const override; private: /*! @@ -83,80 +74,80 @@ class ParserV3 \retval false, if incorrect format is detected. First, check the type of data mode. - Second, call the parsing method for each data type. + Second, call each data item parsing method. */ bool parseData( std::istream & is, - Handler & handler ); + Handler & handler ) const; /*! - \brief parse SHOW_MODE data (short_showinfo_t2) + \brief parse SHOW_MODE inof, actually short_showinfo_t2 \param is reference to the input stream \param handler reference to the data handler object \retval true if successfully parsed. \retval false if failed to parse. */ - bool parseShortShow( std::istream & is, - Handler & handler ); + bool parseShowInfo( std::istream & is, + Handler & handler ) const; /*! - \brief parse MSG_MODE data (msg_info_t) + \brief parse MSG_MODE info(msg_info_t) \param is reference to the input stream \param handler reference to the data handler object \retval true if successfully parsed. \retval false if failed to parse. */ - bool parseMsg( std::istream & is, - Handler & handler ); + bool parseMsgInfo( std::istream & is, + Handler & handler ) const; /*! - \brief parse PM_MODE data (char) + \brief parse PM_MODE info(playmode) \param is reference to the input stream \param handler reference to the data handler object \retval true if successfully parsed. \retval false if failed to parse. */ bool parsePlayMode( std::istream & is, - Handler & handler ); + Handler & handler ) const; /*! - \brief parse TEAM_MODE (team_t * 2) + \brief parse TEAM_MODE info(team_t * 2) \param is reference to the input stream \param handler reference to the data handler object \retval true if successfully parsed. \retval false if failed to parse. */ - bool parseTeam( std::istream & is, - Handler & handler ); + bool parseTeamInfo( std::istream & is, + Handler & handler ) const; /*! - \brief parse PT_MODE (player_type_t) + \brief parse PT_MODE info(player_type_t) \param is reference to the input stream \param handler reference to the data handler object \retval true if successfully parsed. \retval false if failed to parse. */ bool parsePlayerType( std::istream & is, - Handler & handler ); + Handler & handler ) const; /*! - \brief parse PARAM_MODE (server_params_t) + \brief parse PARAM_MODE info(server_params_t) \param is reference to the input stream \param handler reference to the data handler object \retval true if successfully parsed. \retval false if failed to parse. */ bool parseServerParam( std::istream & is, - Handler & handler ); + Handler & handler ) const; /*! - \brief parse PPARAM_MODE (player_params_t) + \brief parse PPARAM_MODE info(player_params_t) \param is reference to the input stream \param handler reference to the data handler object \retval true if successfully parsed. \retval false if failed to parse. */ bool parsePlayerParam( std::istream & is, - Handler & handler ); + Handler & handler ) const; }; } // end of namespace diff --git a/rcss/rcg/parser_v4.cpp b/rcss/rcg/parser_v4.cpp index 06ac13d..a014895 100644 --- a/rcss/rcg/parser_v4.cpp +++ b/rcss/rcg/parser_v4.cpp @@ -38,8 +38,6 @@ #include "handler.h" #include "types.h" -#include -#include #include #include #include @@ -51,9 +49,12 @@ namespace rcss { namespace rcg { /*-------------------------------------------------------------------*/ +/*! + + */ bool ParserV4::parse( std::istream & is, - Handler & handler ) + Handler & handler ) const { // streampos must be the first point!!! is.seekg( 0 ); @@ -71,6 +72,7 @@ ParserV4::parse( std::istream & is, || line.length() < 4 || line.compare( 0, 3, "ULG" ) != 0 ) { + std::cerr << "Unknown header line: [" << line << "]" << std::endl; return false; } @@ -79,11 +81,13 @@ ParserV4::parse( std::istream & is, && version != REC_VERSION_5 && version != REC_VERSION_6 ) { + std::cerr << "Unsupported rcg version: [" << line << "]" << std::endl; return false; } if ( ! handler.handleLogVersion( version ) ) { + std::cerr << "Unsupported game log version: [" << line << "]" << std::endl; return false; } @@ -97,12 +101,12 @@ ParserV4::parse( std::istream & is, } } - if ( ! is.eof() ) + if ( is.eof() ) { - return false; + return handler.handleEOF(); } - return handler.handleEOF(); + return false; } /*-------------------------------------------------------------------*/ @@ -112,14 +116,14 @@ ParserV4::parse( std::istream & is, bool ParserV4::parseLine( const int n_line, const std::string & line, - Handler & handler ) + Handler & handler ) const { char name[32]; if ( std::sscanf( line.c_str(), " ( %s ", name ) != 1 ) { - std::cerr << n_line << ": Illegal line. [" << line << ']' - << std::endl; + std::cerr << n_line << ": Illegal line: [" << line << ']' + << std::endl;; return false; } @@ -153,7 +157,8 @@ ParserV4::parseLine( const int n_line, } else { - std::cerr << n_line << ": Unknown message type. name=" << name << " line=[" << line << ']' + std::cerr << n_line << ": error:" + << " Unknown mode [" << line << ']' << std::endl;; } @@ -167,245 +172,450 @@ ParserV4::parseLine( const int n_line, bool ParserV4::parseShow( const int n_line, const std::string & line, - Handler & handler ) + Handler & handler ) const { /* (show