]> Devoid-pointer.net GitWeb - libHPCS.git/commitdiff
- Add generic support for reading MTH files
authorMichal Malý <madcatxster@devoid-pointer.net>
Thu, 26 Mar 2015 15:22:29 +0000 (16:22 +0100)
committerMichal Malý <madcatxster@devoid-pointer.net>
Thu, 26 Mar 2015 15:22:29 +0000 (16:22 +0100)
- Use ICU on Unix systems to read UTF-16 encoded files
- Implement MTH files reading on Unix
- Add dummy support for MTH files reading on Windows

CMakeLists.txt
FindICU.cmake [new file with mode: 0644]
include/libhpcs.h
libhpcs.c
libhpcs_p.h
test_tool.c

index c503d17f1682aad877525ce3880f0d38f84bb3a5..4aa0dbba4bb7127ab4c75e05b6bc1a34caab5f58 100644 (file)
@@ -3,7 +3,12 @@ include(TestBigEndian)
 
 project(libHPCS)
 
-add_definitions("-std=c89 -Wall")
+set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR})
+add_definitions("-std=c89 -Wall -Wextra")
+
+if (CMAKE_BUILD_TYPE EQUAL "DEBUG")
+  add_definitions("-ggdb -g3")
+endif()
 
 test_big_endian(HAVE_BIG_ENDIAN)
 if (${HAVE_BIG_ENDIAN})
@@ -12,13 +17,20 @@ else()
   add_definitions(-D_HPCS_LITTLE_ENDIAN)
 endif()
 
+find_package(ICU 54 REQUIRED COMPONENTS uc io)
+
 set(libHPCS_SRCS
     libhpcs.c)
 
+include_directories(
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  ${ICU_INCLUDE_DIRS})
+
 add_library(HPCS SHARED ${libHPCS_SRCS})
+target_link_libraries(HPCS PRIVATE ${ICU_LIBRARIES})
 set_target_properties(HPCS
-                     PROPERTIES VERSION 1.0
-                     SOVERSION 1.0)
+                     PROPERTIES VERSION 2.0
+                     SOVERSION 2.0)
 
 if (${BuildTestTool})
   set(libHPCS_test_SRCS
diff --git a/FindICU.cmake b/FindICU.cmake
new file mode 100644 (file)
index 0000000..1646660
--- /dev/null
@@ -0,0 +1,313 @@
+# This module can find the International Components for Unicode (ICU) Library
+#
+# Requirements:
+# - CMake >= 2.8.3 (for new version of find_package_handle_standard_args)
+#
+# The following variables will be defined for your use:
+#   - ICU_FOUND             : were all of your specified components found (include dependencies)?
+#   - ICU_INCLUDE_DIRS      : ICU include directory
+#   - ICU_LIBRARIES         : ICU libraries
+#   - ICU_VERSION           : complete version of ICU (x.y.z)
+#   - ICU_MAJOR_VERSION     : major version of ICU
+#   - ICU_MINOR_VERSION     : minor version of ICU
+#   - ICU_PATCH_VERSION     : patch version of ICU
+#   - ICU_<COMPONENT>_FOUND : were <COMPONENT> found? (FALSE for non specified component if it is not a dependency)
+#
+# For windows or non standard installation, define ICU_ROOT variable to point to the root installation of ICU. Two ways:
+#   - run cmake with -DICU_ROOT=<PATH>
+#   - define an environment variable with the same name before running cmake
+# With cmake-gui, before pressing "Configure":
+#   1) Press "Add Entry" button
+#   2) Add a new entry defined as:
+#     - Name: ICU_ROOT
+#     - Type: choose PATH in the selection list
+#     - Press "..." button and select the root installation of ICU
+#
+# Example Usage:
+#
+#   1. Copy this file in the root of your project source directory
+#   2. Then, tell CMake to search this non-standard module in your project directory by adding to your CMakeLists.txt:
+#     set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR})
+#   3. Finally call find_package() once, here are some examples to pick from
+#
+#   Require ICU 4.4 or later
+#     find_package(ICU 4.4 REQUIRED)
+#
+#   if(ICU_FOUND)
+#      include_directories(${ICU_INCLUDE_DIRS})
+#      add_executable(myapp myapp.c)
+#      target_link_libraries(myapp ${ICU_LIBRARIES})
+#   endif(ICU_FOUND)
+
+#=============================================================================
+# Copyright (c) 2011-2013, julp
+#
+# Distributed under the OSI-approved BSD License
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#=============================================================================
+
+find_package(PkgConfig QUIET)
+
+########## Private ##########
+if(NOT DEFINED ICU_PUBLIC_VAR_NS)
+    set(ICU_PUBLIC_VAR_NS "ICU")                          # Prefix for all ICU relative public variables
+endif(NOT DEFINED ICU_PUBLIC_VAR_NS)
+if(NOT DEFINED ICU_PRIVATE_VAR_NS)
+    set(ICU_PRIVATE_VAR_NS "_${ICU_PUBLIC_VAR_NS}")       # Prefix for all ICU relative internal variables
+endif(NOT DEFINED ICU_PRIVATE_VAR_NS)
+if(NOT DEFINED PC_ICU_PRIVATE_VAR_NS)
+    set(PC_ICU_PRIVATE_VAR_NS "_PC${ICU_PRIVATE_VAR_NS}") # Prefix for all pkg-config relative internal variables
+endif(NOT DEFINED PC_ICU_PRIVATE_VAR_NS)
+
+function(icudebug _VARNAME)
+    if(${ICU_PUBLIC_VAR_NS}_DEBUG)
+        if(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+            message("${ICU_PUBLIC_VAR_NS}_${_VARNAME} = ${${ICU_PUBLIC_VAR_NS}_${_VARNAME}}")
+        else(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+            message("${ICU_PUBLIC_VAR_NS}_${_VARNAME} = <UNDEFINED>")
+        endif(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+    endif(${ICU_PUBLIC_VAR_NS}_DEBUG)
+endfunction(icudebug)
+
+set(${ICU_PRIVATE_VAR_NS}_ROOT "")
+if(DEFINED ENV{ICU_ROOT})
+    set(${ICU_PRIVATE_VAR_NS}_ROOT "$ENV{ICU_ROOT}")
+endif(DEFINED ENV{ICU_ROOT})
+if (DEFINED ICU_ROOT)
+    set(${ICU_PRIVATE_VAR_NS}_ROOT "${ICU_ROOT}")
+endif(DEFINED ICU_ROOT)
+
+set(${ICU_PRIVATE_VAR_NS}_BIN_SUFFIXES )
+set(${ICU_PRIVATE_VAR_NS}_LIB_SUFFIXES )
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+    list(APPEND ${ICU_PRIVATE_VAR_NS}_BIN_SUFFIXES "bin64")
+    list(APPEND ${ICU_PRIVATE_VAR_NS}_LIB_SUFFIXES "lib64")
+endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
+list(APPEND ${ICU_PRIVATE_VAR_NS}_BIN_SUFFIXES "bin")
+list(APPEND ${ICU_PRIVATE_VAR_NS}_LIB_SUFFIXES "lib")
+
+set(${ICU_PRIVATE_VAR_NS}_COMPONENTS )
+# <icu component name> <library name 1> ... <library name N>
+macro(icu_declare_component _NAME)
+    list(APPEND ${ICU_PRIVATE_VAR_NS}_COMPONENTS ${_NAME})
+    set("${ICU_PRIVATE_VAR_NS}_COMPONENTS_${_NAME}" ${ARGN})
+endmacro(icu_declare_component)
+
+icu_declare_component(data icudata)
+icu_declare_component(uc   icuuc)         # Common and Data libraries
+icu_declare_component(i18n icui18n icuin) # Internationalization library
+icu_declare_component(io   icuio ustdio)  # Stream and I/O Library
+icu_declare_component(le   icule)         # Layout library
+icu_declare_component(lx   iculx)         # Paragraph Layout library
+
+########## Public ##########
+set(${ICU_PUBLIC_VAR_NS}_FOUND TRUE)
+set(${ICU_PUBLIC_VAR_NS}_LIBRARIES )
+set(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS )
+set(${ICU_PUBLIC_VAR_NS}_C_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CXX_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CPP_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_C_SHARED_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CXX_SHARED_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CPP_SHARED_FLAGS "")
+foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PRIVATE_VAR_NS}_COMPONENTS})
+    string(TOUPPER "${${ICU_PRIVATE_VAR_NS}_COMPONENT}" ${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT)
+    set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" FALSE) # may be done in the icu_declare_component macro
+endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+
+# Check components
+if(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS) # uc required at least
+    set(${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS uc)
+else(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+    list(APPEND ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS uc)
+    list(REMOVE_DUPLICATES ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+    foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+        if(NOT DEFINED ${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+            message(FATAL_ERROR "Unknown ICU component: ${${ICU_PRIVATE_VAR_NS}_COMPONENT}")
+        endif(NOT DEFINED ${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+    endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+endif(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+
+# Includes
+find_path(
+    ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS
+    NAMES unicode/utypes.h utypes.h
+    HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT}
+    PATH_SUFFIXES "include"
+    DOC "Include directories for ICU"
+)
+
+if(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+    ########## <part to keep synced with tests/version/CMakeLists.txt> ##########
+    if(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uvernum.h") # ICU >= 4
+        file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uvernum.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+    elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uversion.h") # ICU [2;4[
+        file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uversion.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+    elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/utypes.h") # ICU [1.4;2[
+        file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/utypes.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+    elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/utypes.h") # ICU 1.3
+        file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/utypes.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+    else()
+        message(FATAL_ERROR "ICU version header not found")
+    endif()
+
+    if(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *ICU_VERSION *\"([0-9]+)\".*") # ICU 1.3
+        # [1.3;1.4[ as #define ICU_VERSION "3" (no patch version, ie all 1.3.X versions will be detected as 1.3.0)
+        set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "1")
+        set(${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_1}")
+        set(${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "0")
+    elseif(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *U_ICU_VERSION_MAJOR_NUM *([0-9]+).*")
+        #
+        # Since version 4.9.1, ICU release version numbering was totaly changed, see:
+        # - http://site.icu-project.org/download/49
+        # - http://userguide.icu-project.org/design#TOC-Version-Numbers-in-ICU
+        #
+        set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}")
+        string(REGEX REPLACE ".*# *define *U_ICU_VERSION_MINOR_NUM *([0-9]+).*" "\\1" ${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS}")
+        string(REGEX REPLACE ".*# *define *U_ICU_VERSION_PATCHLEVEL_NUM *([0-9]+).*" "\\1" ${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "${${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS}")
+    elseif(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *U_ICU_VERSION *\"(([0-9]+)(\\.[0-9]+)*)\".*") # ICU [1.4;1.8[
+        # [1.4;1.8[ as #define U_ICU_VERSION "1.4.1.2" but it seems that some 1.4.1(?:\.\d)? have releasing error and appears as 1.4.0
+        set(${ICU_PRIVATE_VAR_NS}_FULL_VERSION "${CMAKE_MATCH_1}") # copy CMAKE_MATCH_1, no longer valid on the following if
+        if(${ICU_PRIVATE_VAR_NS}_FULL_VERSION MATCHES "^([0-9]+)\\.([0-9]+)$")
+            set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}")
+            set(${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_2}")
+            set(${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "0")
+        elseif(${ICU_PRIVATE_VAR_NS}_FULL_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)")
+            set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}")
+            set(${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_2}")
+            set(${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "${CMAKE_MATCH_3}")
+        endif()
+    else()
+        message(FATAL_ERROR "failed to detect ICU version")
+    endif()
+    set(${ICU_PUBLIC_VAR_NS}_VERSION "${${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION}.${${ICU_PUBLIC_VAR_NS}_MINOR_VERSION}.${${ICU_PUBLIC_VAR_NS}_PATCH_VERSION}")
+    ########## </part to keep synced with tests/version/CMakeLists.txt> ##########
+
+    # Check dependencies (implies pkg-config)
+    if(PKG_CONFIG_FOUND)
+        set(${ICU_PRIVATE_VAR_NS}_COMPONENTS_DUP ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+        foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PRIVATE_VAR_NS}_COMPONENTS_DUP})
+            pkg_check_modules(PC_ICU_PRIVATE_VAR_NS "icu-${${ICU_PRIVATE_VAR_NS}_COMPONENT}" QUIET)
+
+            if(${PC_ICU_PRIVATE_VAR_NS}_FOUND)
+                foreach(${PC_ICU_PRIVATE_VAR_NS}_LIBRARY ${PC_ICU_LIBRARIES})
+                    string(REGEX REPLACE "^icu" "" ${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY ${${PC_ICU_PRIVATE_VAR_NS}_LIBRARY})
+                    list(APPEND ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS ${${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY})
+                endforeach(${PC_ICU_PRIVATE_VAR_NS}_LIBRARY)
+            endif(${PC_ICU_PRIVATE_VAR_NS}_FOUND)
+        endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+        list(REMOVE_DUPLICATES ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+    endif(PKG_CONFIG_FOUND)
+
+    # Check libraries
+    foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+        set(${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES )
+        set(${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES )
+        foreach(${ICU_PRIVATE_VAR_NS}_BASE_NAME ${${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT}})
+            list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}")
+            list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}d")
+            list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}${ICU_MAJOR_VERSION}${ICU_MINOR_VERSION}")
+            list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}${ICU_MAJOR_VERSION}${ICU_MINOR_VERSION}d")
+        endforeach(${ICU_PRIVATE_VAR_NS}_BASE_NAME)
+
+        find_library(
+            ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}
+            NAMES ${${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES}
+            HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT}
+            PATH_SUFFIXES ${_ICU_LIB_SUFFIXES}
+            DOC "Release libraries for ICU"
+        )
+        find_library(
+            ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}
+            NAMES ${${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES}
+            HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT}
+            PATH_SUFFIXES ${_ICU_LIB_SUFFIXES}
+            DOC "Debug libraries for ICU"
+        )
+
+        string(TOUPPER "${${ICU_PRIVATE_VAR_NS}_COMPONENT}" ${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT)
+        if(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # both not found
+            set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" FALSE)
+            set("${ICU_PUBLIC_VAR_NS}_FOUND" FALSE)
+        else(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # one or both found
+            set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" TRUE)
+            if(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # release not found => we are in debug
+                set(${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT} "${${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}")
+            elseif(NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # debug not found => we are in release
+                set(${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT} "${${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}")
+            else() # both found
+                set(
+                    ${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT}
+                    optimized ${${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}
+                    debug ${${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}
+                )
+            endif()
+            list(APPEND ${ICU_PUBLIC_VAR_NS}_LIBRARIES ${${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT}})
+        endif(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+    endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+
+    # Try to find out compiler flags
+    find_program(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE icu-config HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT})
+    if(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE)
+        execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_C_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+        execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cxxflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CXX_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+        execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cppflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CPP_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+        execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_C_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+        execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cxxflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CXX_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+        execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cppflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CPP_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+    endif(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE)
+
+    # Check find_package arguments
+    include(FindPackageHandleStandardArgs)
+    if(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+        find_package_handle_standard_args(
+            ${ICU_PUBLIC_VAR_NS}
+            REQUIRED_VARS ${ICU_PUBLIC_VAR_NS}_LIBRARIES ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS
+            VERSION_VAR ${ICU_PUBLIC_VAR_NS}_VERSION
+        )
+    else(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+        find_package_handle_standard_args(${ICU_PUBLIC_VAR_NS} "ICU not found" ${ICU_PUBLIC_VAR_NS}_LIBRARIES ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+    endif(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+else(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+    if(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+        message(FATAL_ERROR "Could not find ICU include directory")
+    endif(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+endif(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+
+mark_as_advanced(
+    ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS
+    ${ICU_PUBLIC_VAR_NS}_LIBRARIES
+)
+
+# IN (args)
+icudebug("FIND_COMPONENTS")
+icudebug("FIND_REQUIRED")
+icudebug("FIND_QUIETLY")
+icudebug("FIND_VERSION")
+# OUT
+# Found
+icudebug("FOUND")
+icudebug("UC_FOUND")
+icudebug("I18N_FOUND")
+icudebug("IO_FOUND")
+icudebug("LE_FOUND")
+icudebug("LX_FOUND")
+icudebug("DATA_FOUND")
+# Flags
+icudebug("C_FLAGS")
+icudebug("CPP_FLAGS")
+icudebug("CXX_FLAGS")
+icudebug("C_SHARED_FLAGS")
+icudebug("CPP_SHARED_FLAGS")
+icudebug("CXX_SHARED_FLAGS")
+# Linking
+icudebug("INCLUDE_DIRS")
+icudebug("LIBRARIES")
+# Version
+icudebug("MAJOR_VERSION")
+icudebug("MINOR_VERSION")
+icudebug("PATCH_VERSION")
+icudebug("VERSION")
index 07a28582828be8a4cdeee41c531bbf7d357a5fcf..02f53a049524ab4161bc3ebc61acd1439a50f398 100644 (file)
@@ -29,7 +29,8 @@ enum HPCS_RetCode {
        HPCS_E_NULLPTR,
        HPCS_E_CANT_OPEN,
        HPCS_E_PARSE_ERROR,
-       HPCS_E_UNKNOWN_TYPE
+       HPCS_E_UNKNOWN_TYPE,
+       HPCS_E_NOTIMPL
 };
 
 struct HPCS_Date {
@@ -68,10 +69,23 @@ struct HPCS_MeasuredData {
        size_t data_count;
 };
 
-LIBHPCS_API struct HPCS_MeasuredData* LIBHPCS_CC hpcs_alloc();
-LIBHPCS_API void LIBHPCS_CC hpcs_free(struct HPCS_MeasuredData* const mdata);
+struct HPCS_MethodInfoBlock {
+       char* name;
+       char* value;
+};
+
+struct HPCS_MethodInfo {
+       struct HPCS_MethodInfoBlock* blocks;
+       size_t count;
+};
+
+LIBHPCS_API struct HPCS_MeasuredData* LIBHPCS_CC hpcs_alloc_mdata();
+LIBHPCS_API struct HPCS_MethodInfo* LIBHPCS_CC hpcs_alloc_minfo();
+LIBHPCS_API void LIBHPCS_CC hpcs_free_mdata(struct HPCS_MeasuredData* const mdata);
+LIBHPCS_API void LIBHPCS_CC hpcs_free_minfo(struct HPCS_MethodInfo* const minfo);
 LIBHPCS_API char* LIBHPCS_CC hpcs_error_to_string(const enum HPCS_RetCode);
-LIBHPCS_API enum HPCS_RetCode LIBHPCS_CC hpcs_read_file(const char* filename, struct HPCS_MeasuredData* mdata);
+LIBHPCS_API enum HPCS_RetCode LIBHPCS_CC hpcs_read_mdata(const char* filename, struct HPCS_MeasuredData* mdata);
+LIBHPCS_API enum HPCS_RetCode LIBHPCS_CC hpcs_read_minfo(const char* filename, struct HPCS_MethodInfo* minfo);
 
 #ifdef __cplusplus
 }
index 147a9899a27ef15910b966fdf8d456a827144285..7dd522631800554a8783a4ab1b2cd1de94f5fd99 100644 (file)
--- a/libhpcs.c
+++ b/libhpcs.c
@@ -1,6 +1,12 @@
 #include "include/libhpcs.h"
 #include "libhpcs_p.h"
 
+#ifdef _WIN32
+/* Blank for now */
+#else
+#include <unicode/ustdio.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -8,7 +14,7 @@ extern "C" {
 #include <stdlib.h>
 #include <string.h>
 
-struct HPCS_MeasuredData* hpcs_alloc()
+struct HPCS_MeasuredData* hpcs_alloc_mdata()
 {
        struct HPCS_MeasuredData* mdata = malloc(sizeof(struct HPCS_MeasuredData));
        if (mdata == NULL)
@@ -26,6 +32,18 @@ struct HPCS_MeasuredData* hpcs_alloc()
        return mdata;
 }
 
+struct HPCS_MethodInfo* hpcs_alloc_minfo()
+{
+       struct HPCS_MethodInfo* minfo = malloc(sizeof(struct HPCS_MeasuredData));
+       if (minfo == NULL)
+               return NULL;
+
+       minfo->blocks = NULL;
+       minfo->count = 0;
+
+       return minfo;
+}
+
 char* hpcs_error_to_string(const enum HPCS_RetCode err)
 {
        char* msg;
@@ -58,7 +76,7 @@ char* hpcs_error_to_string(const enum HPCS_RetCode err)
        }
 }
 
-void hpcs_free(struct HPCS_MeasuredData* const mdata)
+void hpcs_free_mdata(struct HPCS_MeasuredData* const mdata)
 {
        if (mdata == NULL)
                return;
@@ -73,7 +91,23 @@ void hpcs_free(struct HPCS_MeasuredData* const mdata)
        free(mdata);
 }
 
-enum HPCS_RetCode hpcs_read_file(const char* filename, struct HPCS_MeasuredData* mdata)
+void hpcs_free_minfo(struct HPCS_MethodInfo* const minfo)
+{
+       size_t idx;
+
+       if (minfo == NULL)
+               return;
+
+       for (idx = 0; idx < minfo->count; idx++) {
+               free(minfo->blocks[idx].name);
+               free(minfo->blocks[idx].value);
+       }
+
+       free(minfo->blocks);
+       free(minfo);
+}
+
+enum HPCS_RetCode hpcs_read_mdata(const char* filename, struct HPCS_MeasuredData* mdata)
 {
         FILE* datafile;
        enum HPCS_ParseCode pret;
@@ -194,6 +228,25 @@ out:
        return ret;
 }
 
+enum HPCS_RetCode hpcs_read_minfo(const char* filename, struct HPCS_MethodInfo* minfo)
+{
+       enum HPCS_ParseCode pret;
+       HPCS_UFH fh;
+
+       if (minfo == NULL)
+               return HPCS_E_NULLPTR;
+
+       fh = open_data_file(filename);
+       if (fh == NULL)
+               return HPCS_E_CANT_OPEN;
+
+       pret = read_method_info_file(fh, minfo);
+       if (pret != PARSE_OK)
+               return HPCS_E_PARSE_ERROR;
+
+       return HPCS_OK;
+}
+
 static enum HPCS_ParseCode autodetect_file_type(FILE* datafile, enum HPCS_FileType* file_type, const bool p_means_pressure)
 {
        char* type_id;
@@ -284,6 +337,34 @@ static void guess_sampling_rate(struct HPCS_MeasuredData* mdata)
        }
 }
 
+
+static enum HPCS_ParseCode next_native_line(HPCS_UFH fh, HPCS_NChar* line, int32_t length)
+{
+#ifdef _WIN32
+       return __win32_next_native_line(fh, line, length);
+#else
+       return __unix_next_native_line(fh, line, length);
+#endif
+}
+
+static HPCS_UFH open_data_file(const char* filename)
+{
+#ifdef _WIN32
+       return __win32_open_data_file(filename);
+#else
+       return __unix_open_data_file(filename);
+#endif
+}
+
+static enum HPCS_ParseCode parse_native_method_info_line(char** name, char** value, HPCS_NChar* line)
+{
+#ifdef _WIN32
+       return __win32_parse_native_method_info_line(name, value, line);
+#else
+       return __unix_parse_native_method_info_line(name, value, line);
+#endif
+}
+
 static enum HPCS_ParseCode read_dad_wavelength(FILE* datafile, struct HPCS_Wavelength* const measured, struct HPCS_Wavelength* const reference)
 {
        char* start_idx, *interv_idx, *end_idx, *temp, *str;
@@ -496,6 +577,44 @@ static uint8_t month_to_number(const char* month)
                return 0;
 }
 
+static enum HPCS_ParseCode read_method_info_file(HPCS_UFH fh, struct HPCS_MethodInfo* minfo)
+{
+       HPCS_NChar line[64];
+       size_t allocated = 0;
+
+       while (next_native_line(fh, line, 64) == PARSE_OK) {
+               enum HPCS_ParseCode pret;
+               char* name = NULL;
+               char* value = NULL;
+
+               pret = parse_native_method_info_line(&name, &value, line);
+               if (pret != PARSE_OK)
+                       return pret;
+
+               if (minfo->count+1 > allocated) {
+                       size_t to_allocate;
+                       if (allocated == 0)
+                               to_allocate = 256;
+                       else
+                           to_allocate = allocated * 2;
+
+                       struct HPCS_MethodInfoBlock* new_blocks = realloc(minfo->blocks, to_allocate * sizeof(struct HPCS_MethodInfoBlock));
+                       if (new_blocks == NULL)
+                               return PARSE_E_NO_MEM;
+                       else {
+                               minfo->blocks = new_blocks;
+                               allocated = to_allocate;
+                       }
+               }
+
+               minfo->blocks[minfo->count].name = name;
+               minfo->blocks[minfo->count].value = value;
+               minfo->count++;
+       }
+
+       return PARSE_OK;
+}
+
 static enum HPCS_ParseCode read_signal(FILE* datafile, struct HPCS_TVPair** pairs, size_t* pairs_count,
                                       const HPCS_step step, const double sampling_rate)
 {
@@ -665,6 +784,121 @@ static enum HPCS_ParseCode read_string_at_offset(FILE* datafile, const HPCS_offs
        return PARSE_OK;
 }
 
+/** Platform-specific functions */
+
+#ifdef _WIN32
+static enum HPCS_ParseCode __win32_next_native_line(HPCS_UFH fh, HPCS_NChar* line, int32_t length)
+{
+       /* Not implemented */
+       return PARSE_E_CANT_READ;
+}
+
+static HPCS_UFH __win32_open_data_file(const char* filename)
+{
+       /* Not implemented */
+       return NULL;
+}
+
+static enum HPCS_ParseCode __win32_parse_native_method_info_line(char** name, char** value, UChar* line)
+{
+       /* Not implemented */
+       return PARSE_E_CANT_READ;
+}
+#else
+static void __unix_hpcs_initialize()
+{
+       /* Initialize all Unicode strings */
+       __ICU_INIT_STRING(EQUALITY_SIGN, "\\x3d");
+       __ICU_INIT_STRING(CR_LF, "\\x0d\\x0a");
+}
+
+static void __unix_hpcs_destroy()
+{
+       free(EQUALITY_SIGN);
+       free(CR_LF);
+}
+
+static enum HPCS_ParseCode __unix_icu_to_utf8(char** target, const UChar* s)
+{
+       UChar32 c;
+       UErrorCode uec = U_ZERO_ERROR;
+       int32_t utf8_size = 0;
+       int32_t idx = 0;
+#ifndef NDEBUG
+       int32_t wrt_size;
+#define pWrt_size &wrt_size
+#else
+#define pWrt_size NULL
+#endif
+
+       do {
+               U16_NEXT(s, idx, -1, c);
+               utf8_size += U8_LENGTH(c);
+       } while (c != 0);
+
+       *target = malloc(utf8_size);
+       if (*target == NULL)
+               return PARSE_E_NO_MEM;
+
+       u_strToUTF8(*target, utf8_size, pWrt_size, s, -1, &uec);
+
+       PR_DEBUGF("Memory allocated: %d, Units written: %d, UEC: %x\n", utf8_size, wrt_size, uec);
+       PR_DEBUGF("Resulting string: %s\n", *target);
+
+       if (U_FAILURE(uec)) {
+               PR_DEBUGF("ICU error: %s\n", u_errorName(uec));
+               free(*target);
+               return PARSE_E_CANT_READ;
+       }
+
+       return PARSE_OK;
+}
+
+static enum HPCS_ParseCode __unix_next_native_line(UFILE* fh, UChar* line, int32_t length)
+{
+       if (u_fgets(line, length, fh) == NULL)
+               return PARSE_E_CANT_READ;
+
+       return PARSE_OK;
+}
+
+static UFILE* __unix_open_data_file(const char* filename)
+{
+       return u_fopen(filename, "r", "en_US", "UTF-16");
+}
+
+static enum HPCS_ParseCode __unix_parse_native_method_info_line(char** name, char** value, UChar* line)
+{
+       UChar* u_name;
+       UChar* u_value;
+       UChar* saveptr;
+       UChar* newline;
+       enum HPCS_ParseCode ret;
+
+       u_name = u_strtok_r(line, EQUALITY_SIGN, &saveptr);
+       if (u_name == NULL)
+               return PARSE_E_NOT_FOUND;
+       u_value = u_strtok_r(NULL, EQUALITY_SIGN, &saveptr);
+       if (u_value == NULL) {
+               free(u_name);
+               return PARSE_E_NOT_FOUND;
+       }
+       /* Remove the trailing \n from value if present */
+       newline = u_strrstr(u_value, CR_LF);
+       if (newline != NULL)
+               *newline = (UChar)0;
+
+       ret = __unix_icu_to_utf8(name, u_name);
+       if (ret != PARSE_OK)
+               return ret;
+       ret = __unix_icu_to_utf8(value, u_value);
+       if (ret != PARSE_OK)
+               return ret;
+
+       return PARSE_OK;
+}
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index f0b4b6b610a91123649a7e0658759512ead490a6..43f96d132ce14f53ab27e518caed6099c27477f3 100644 (file)
@@ -11,6 +11,15 @@ typedef int bool;
 #endif
 #include <stdio.h>
 
+#ifdef _WIN32
+#error "Not defined yet!"
+#else
+#include <unicode/ustdio.h>
+#include <unicode/ustring.h>
+#define HPCS_NChar UChar
+#define HPCS_UFH UFILE*
+#endif
+
 enum HPCS_DataCheckCode {
        DCHECK_GOT_MARKER,
        DCHECK_EOF,
@@ -107,20 +116,52 @@ const char* HPCS_E_PARSE_ERROR_STR = "Cannot parse the specified file, it might
 const char* HPCS_E_UNKNOWN_TYPE_STR = "The specified file contains an unknown type of measurement.";
 const char* HPCS_E__UNKNOWN_EC_STR = "Unknown error code.";
 
+#ifdef _WIN32
+#error "Not implemented yet"
+#else
+/* ICU strings declarations */
+UChar* EQUALITY_SIGN;
+UChar* CR_LF;
+#endif
+
 static enum HPCS_ParseCode autodetect_file_type(FILE* datafile, enum HPCS_FileType* file_type, const bool p_means_pressure);
 static enum HPCS_DataCheckCode check_for_marker(const char* segment, size_t* const next_marker_idx);
 static HPCS_step guess_current_step(const struct HPCS_MeasuredData* mdata);
 static HPCS_step guess_elec_sigstep(const struct HPCS_MeasuredData *mdata);
 static bool guess_p_meaning(const struct HPCS_MeasuredData* mdata);
 static void guess_sampling_rate(struct HPCS_MeasuredData* mdata);
+static enum HPCS_ParseCode next_native_line(HPCS_UFH fh, HPCS_NChar* line, int32_t length);
+static HPCS_UFH open_data_file(const char* filename);
+static enum HPCS_ParseCode parse_native_method_info_line(char** name, char** value, HPCS_NChar* line);
 static enum HPCS_ParseCode read_dad_wavelength(FILE* datafile, struct HPCS_Wavelength* const measured, struct HPCS_Wavelength* const reference);
 static uint8_t month_to_number(const char* month);
 static enum HPCS_ParseCode read_date(FILE* datafile, struct HPCS_Date* date);
+static enum HPCS_ParseCode read_method_info_file(HPCS_UFH fh, struct HPCS_MethodInfo* minfo);
 static enum HPCS_ParseCode read_signal(FILE* datafile, struct HPCS_TVPair** pairs, size_t* pairs_count,
                                       const HPCS_step step, const double sampling_rate);
 static enum HPCS_ParseCode read_sampling_rate(FILE* datafile, double* sampling_rate);
 static enum HPCS_ParseCode read_string_at_offset(FILE* datafile, const HPCS_offset, char** const result);
 
+/** Platform-specific functions */
+#ifdef _WIN32
+static enum HPCS_ParseCode __win32_next_native_line(HPCS_UFH, HPCS_NChar* line, int32_t length);
+static HPCS_UFH __win32_open_data_file(const char* filename);
+static enum HPCS_ParseCode __win32_parse_native_method_info_line(char** name, char** value, HPCS_NChar* line);
+#else
+static void __attribute((constructor)) __unix_hpcs_initialize();
+static void __attribute((destructor)) __unix_hpcs_destroy();
+static enum HPCS_ParseCode __unix_icu_to_utf8(char** target, const UChar* s);
+static HPCS_UFH __unix_open_data_file(const char* filename);
+static enum HPCS_ParseCode __unix_next_native_line(UFILE* fh, UChar* line, int32_t length);
+static enum HPCS_ParseCode __unix_parse_native_method_info_line(char** name, char** value, UChar* line);
+
+#define __ICU_INIT_STRING(dst, s) do { \
+       UChar temp[64]; \
+       int32_t length = u_unescape(s, temp, sizeof(temp)); \
+       dst = calloc(length + 1, sizeof(UChar)); \
+       u_strcpy(dst, temp); \
+} while(0)
+#endif
 
 #ifdef _HPCS_LITTLE_ENDIAN
 #define be_to_cpu(bytes) reverse_endianness((char*)bytes, sizeof(bytes));
@@ -148,7 +189,7 @@ void reverse_endianness(char* bytes, size_t sz) {
  #define PR_DEBUGF(fmt, ...) fprintf(stderr, "[%s()] "fmt, __func__, __VA_ARGS__)
  #define PR_DEBUG(msg) fprintf(stderr, "[%s()] "msg, __func__)
 #else
- #define PR_DEBUGF(fmt, msg) ((void)0)
+ #define PR_DEBUGF(fmt, ...) ((void)0)
  #define PR_DEBUG(msg) ((void)0)
 #endif
 
index fb86a5c3210dcd51b682cbbe4f80a2ed7bbad994..144796126149229d2b91ccc1985ec91c081746e7 100644 (file)
@@ -1,26 +1,22 @@
 #include <float.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include "include/libhpcs.h"
 
-int main(int argc, char** argv)
+int read_data(const char* path)
 {
        struct HPCS_MeasuredData* mdata;
        enum HPCS_RetCode hret;
        size_t di;
-       
-       if (argc < 2) {
-               printf("No filename specified\n");
-               return EXIT_FAILURE;
-       }
 
-       mdata = hpcs_alloc();
+       mdata = hpcs_alloc_mdata();
        if (mdata == NULL) {
                printf("Out of memory\n");
                return EXIT_FAILURE;
        }
 
-       hret = hpcs_read_file(argv[1], mdata);
+       hret = hpcs_read_mdata(path, mdata);
        if (hret != HPCS_OK) {
                printf("Cannot parse file: %s\n", hpcs_error_to_string(hret));
                return EXIT_FAILURE;
@@ -29,7 +25,56 @@ int main(int argc, char** argv)
        for (di = 0; di < mdata->data_count; di++)
                printf("Time: %.17lg, Value: %.17lg\n", mdata->data[di].time, mdata->data[di].value);
 
-       hpcs_free(mdata);
+       hpcs_free_mdata(mdata);
 
        return EXIT_SUCCESS;
 }
+
+int read_info(const char* path)
+{
+       struct HPCS_MethodInfo* minfo;
+       enum HPCS_RetCode hret;
+       size_t di;
+
+       minfo = hpcs_alloc_minfo();
+       if (minfo == NULL) {
+               printf("Out of memory\n");
+               return EXIT_FAILURE;
+       }
+
+       hret = hpcs_read_minfo(path, minfo);
+       if (hret != HPCS_OK) {
+               printf("Cannot parse file: %s\n", hpcs_error_to_string(hret));
+               return EXIT_FAILURE;
+       }
+
+       for (di = 0; di < minfo->count; di++) {
+               struct HPCS_MethodInfoBlock* b = &minfo->blocks[di];
+               printf("Name: %s = Value: %s\n", b->name, b->value);
+       }
+
+       hpcs_free_minfo(minfo);
+
+       return EXIT_SUCCESS;
+}
+
+int main(int argc, char** argv)
+{
+       if (argc < 3) {
+               printf("Not enough arguments\n");
+               printf("Usage: test_tool MODE FILE\n");
+               printf("MODE: d - read data file\n"
+                      "      i - method info\n"
+                      "FILE: path\n");
+               return EXIT_FAILURE;
+       }
+
+       if (strcmp(argv[1], "d") == 0)
+               return read_data(argv[2]);
+       else if (strcmp(argv[1], "i") == 0)
+               return read_info(argv[2]);
+       else {
+               printf("Invalid mode argument\n");
+               return EXIT_FAILURE;
+       }
+}